JSFiddle - React, Tailwind, and code Playground
by Gwyn Milcote
HTML
Clothing editor. Design multiple layers, move order up or down.<br>
<fieldset id='attire_create_container'>
<legend>Create New Layer</legend>
<span id='attire_create_info'>msg about no layers, or warn of max</span>
<select id='attire_create_type'>...</select>
<button id='attire_create_btn'>Create</button>
</fieldset>
<fieldset id='attire_layers_container'>
<legend>Layer List</legend>
<div id='attire_layers'>Layers here...</div>
</fieldset>
<fieldset id='attire_edit_container'>
<legend>Edit Layer</legend>
<span id='attire_info'>Description here...</span>
<div id='attire_inputs'>Dropdowns here...</div>
</fieldset>
<div class='coat_container coat_full'>
<div id='dragon_coat'>Coat layers here...</div>
<div id='dragon_attire'>Attire layers here, in own divs...</div>
</div>
CSS
.coat_container {
margin: 20px auto;
position: relative;
border: 1px solid green;
}
.coat_container img {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
.coat_full {
width: 400px;
height: 300px;
}
/*
* Up to 4 wearable pieces, in own divs.
* z-index is swapped, for 'layer orders'.
*//*
.z_1 { z-index: 1; }
.z_2 { z-index: 2; }
.z_3 { z-index: 3; }
.z_4 { z-index: 4; }
.z_5 { z-index: 5; }
.z_6 { z-index: 6; }
.z_7 { z-index: 7; }
.z_8 { z-index: 8; }
*/
.attire_layer {
padding: 5px;
border: 1px solid silver;
display: flex;
flex-flow: row wrap;
}
.attire_layer span {
flex: 111;
cursor: pointer;
}
.attire_selected {
border: 1px solid orange;
background: gold;
}
fieldset {
margin: 15px auto;
}
fieldset legend {
padding: 5px 10px;
border: 1px solid grey;
}
.pink {filter: invert(39%) sepia(83%) saturate(666%) hue-rotate(284deg) brightness(94%) contrast(91%);}
.slate {filter: invert(60%) sepia(34%) saturate(240%) hue-rotate(184deg) brightness(92%) contrast(94%);}
.red {filter: invert(29%) sepia(89%) saturate(3528%) hue-rotate(345deg) brightness(107%) contrast(80%);}
.brown {filter: invert(54%) sepia(22%) saturate(1039%) hue-rotate(333deg) brightness(93%) contrast(90%);}
.orange {filter: invert(53%) sepia(34%) saturate(3679%) hue-rotate(1deg) brightness(96%) contrast(104%);}
.peach {filter: invert(68%) sepia(49%) saturate(449%) hue-rotate(326deg) brightness(103%) contrast(98%);}
.olive {filter: invert(71%) sepia(80%) saturate(425%) hue-rotate(21deg) brightness(90%) contrast(101%);}
.gold {filter: invert(80%) sepia(77%) saturate(5230%) hue-rotate(1deg) brightness(105%) contrast(102%);}
.green {filter: invert(58%) sepia(83%) saturate(544%) hue-rotate(65deg) brightness(94%) contrast(94%);}
.blue {filter: invert(84%) sepia(29%) saturate(5255%) hue-rotate(136deg) brightness(96%) contrast(95%);}
.teal {filter: invert(65%) sepia(79%) saturate(281%) hue-rotate(118deg)...
JavaScript
let path = "http://griffusion.elementfx.com/demo/attire/";
/*
* Each dragon has own number of slots for wearables.
*/
let dragonSlots = 4;
let terms = {
colours: ["blue","green","red","gold","orange","peach","brown","silver","black","white","olive","pink","indigo","slate","teal"],
baseTypes: ["cloak","boots","scarf"],
patternTypes: ["stripes","spots","stars"],
decorTypes: ["trim","ribbon","tassels"],
// Contain wearable objects here.
layers: [],
lastID: 1,
currentPiece: {},
// Handy template to clone.
blank: {bC: 1, bT: 1, pC: 1, pT: 0, dC: 1, dT: 0},
// Deep-clone that blank wearable object.
getBlank: function(){
return Object.assign({}, terms.blank);
},
getColourName: function(n){
if(n < 1 || n > terms.colours.length){
throw "terms.getColourName(): invalid number, " + n;
}
return terms.colours[n - 1];
},
getBaseType: function(n){
if(n < 1 || n > terms.baseTypes.length){
throw "terms.getBaseType(): invalid number, " + n;
}
return terms.baseTypes[n - 1];
},
getPatternType: function(n){
if(n < 1 || n > terms.patternTypes.length){
throw "terms.getPatternType(): invalid number, " + n;
}
return terms.patternTypes[n - 1];
},
getDecorType: function(n){
if(n < 1 || n > terms.decorTypes.length){
throw "terms.getDecorType(): invalid number, " + n;
}
return terms.decorTypes[n - 1];
},
/*
* Generate dropdown options for base type.
* Used when creating a new layer. Call on page load.
*/
renderCreateOptions: function(){
let html = "";
for(let i = 0; i < terms.baseTypes.length; i++){
let type = terms.baseTypes[i];
html += "<option value='" + (i+1) + "'>" + type + "</option>";
}
$("#attire_create_type").html(html);
...