JSFiddle - React, Tailwind, and code Playground
by Gwyn Milcote
HTML
Griffin marking calculator. For 'Shrine of the Griffin'. See how tiger, leopard and dusky genes interact to create mixed markings.
<div class='container'>
<div id='mother'>Mother: <span id='parent_info_2'><b>Chiffon</b> (Bright Amber)</span><br>
<div id='parent_coat_2' class='griffin_coat coat_adult'>Rendering...</div>
<select id='f_lm1'>
<option value='Lm^t' selected>Lm^t</option>
<option value='Lm^l'>Lm^l</option>
<option value='lm'>lm</option>
</select>
<select id='f_lm2'>
<option value='Lm^t'>Lm^t</option>
<option value='Lm^l' selected>Lm^l</option>
<option value='lm'>lm</option>
</select>
<select id='f_ag1'>
<option value='Ag'>Ag</option>
<option value='ag' selected>ag</option>
</select>
<select id='f_ag2'>
<option value='Ag'>Ag</option>
<option value='ag' selected>ag</option>
</select>
</div>
<div id='father'>Father: <span id='parent_info_1'><b>Green</b> (Normal Green)</span><br>
<div id='parent_coat_1' class='griffin_coat coat_adult'>Rendering...</div>
<select id='m_lm1'>
<option value='Lm^t'>Lm^t</option>
<option value='Lm^l'>Lm^l</option>
<option value='lm' selected>lm</option>
</select>
<select id='m_lm2'>
<option value='Lm^t'>Lm^t</option>
<option value='Lm^l'>Lm^l</option>
<option value='lm' selected>lm</option>
</select>
<select id='m_ag1'>
<option value='Ag' selected>Ag</option>
<option value='ag'>ag</option>
</select>
<select id='m_ag2'>
<option value='Ag'>Ag</option>
<option value='ag' selected>ag</option>
</select>
</div>
<br><button id='cross'>Cross</button><br>Here are the marking shapes of potential offspring.<br>
<table id='result_table'></table>
</div>
CSS
.container {text-align:center;}
#mother, #father {border:1px solid black;padding:10px;margin:5px;border-radius:5px;display:inline-block;vertical-align:top;}
table {
width: 100%;
border-collapse: collapse;
margin: 20px auto;
}
table td {
border: 1px solid #ddd;
padding: 5px;
text-align: center;
}
table .empty {
border: none;
}
table .header {
font-weight: bold;
background-color: #ddd;
border: 1px solid #bbb;
}
.griffin_coat {
position: relative;
}
.griffin_coat img {
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
}
.coat_adult {
width: 400px;
height: 300px;
}
.coat_teen {
width: 400px;
height: 300px;
}
/* Same for all stages. */
.coat_bigthumb {
width: 200px;
height: 150px;
}
.coat_thumb {
width: 160px;
height: 120px;
}
.coat_small {
width: 120px;
height: 90px;
}
.coat_tiny {
width: 100px;
height: 75px;
}
.multiply {
mix-blend-mode: multiply;
}
.overlay {
mix-blend-mode: soft-light;
}
/*
Classes for each coat colour.
'f' means filters for black PNG images.
'c' means background colour for divs.
1-4 are shades: Base, Faded, Bright, Cream.
*/
.c_red_1 {background-color: #ffcc33;}
.c_red_2 {background-color: #ffcc33;}
.c_red_3 {background-color: #ffcc33;}
.c_red_4 {background-color: #ffcc33;}
/* Red, salmon, amaranth, pink */
.f_red_1 {filter: invert(13%) sepia(59%) saturate(5042%) hue-rotate(354deg) brightness(81%) contrast(90%);}
.f_red_2 {filter: invert(41%) sepia(14%) saturate(6118%) hue-rotate(337deg) brightness(92%) contrast(85%);}
.f_red_3 {filter: invert(58%) sepia(73%) saturate(483%) hue-rotate(308deg) brightness(100%) contrast(108%);}
.f_red_4 {filter: invert(86%) sepia(68%) saturate(1606%) hue-rotate(289deg) brightness(121%) contrast(102%);}
/* Orange, tan, gold, cream */
.f_orange_1 {filter: invert(38%) sepia(72%) saturate(1254%) hue-rotate(358deg) brightness(87%) contrast(98%);}
.f_orange_2...
JavaScript
const path = 'http://mythstable.epizy.com/ootg/images/';
const markNames = {
"dusky_tigard": "Dusky Tigard",
"dusky_tiger": "Dusky Tiger",
"dusky_leopard": "Dusky Leopard",
"dusky": "Dusky",
"tiger": "Tiger",
"leopard": "Leopard",
"tigard": "Tigard"
};
// For assembling image HTML.
class Coat {
constructor(sex, stage, size = ""){
this.path = path + stage + "/";
if(stage > 3){ this.path += sex + "/"; }
if(size != ""){ this.path += size + "/"; } // 150px
this.startCoat();
}
startCoat(){
this.html = "<img src='" + this.path + "ground.png'>\n";
}
addImage(url){
this.html += "<img src='" + this.path + url + ".png'>\n";
}
addFilter(url, css){
this.html += "<img src='" + this.path + url + ".png' class='f_" + css + "'>\n";
}
endCoat(){
//this.html += "<img src='" + this.path + "shading.png'>\n";
//this.html += "<img src='" + this.path + "highlight.png'>\n";
//this.html += "<img src='" + this.path + "line.png'>\n";
this.html += "<img src='" + this.path + "shade.png' class='multiply'>\n";
this.html += "<img src='" + this.path + "shade.png' class='overlay' style='opacity:0.3;'>\n";
this.html += "<img src='" + this.path + "line.png'>\n";
}
output(){
return this.html;
}
}
// Handle the Limiter/Agelaius punnett square.
class MarkCalc {
constructor(){
this.mother = {sex: 2, lm1: "Lm^t", lm2: "Lm^l", ag1: "ag", ag2: "ag"};
this.father = {sex: 1, lm1: "lm", lm2: "lm", ag1: "Ag", ag2: "ag"};
this.updateParent(this.mother);
this.updateParent(this.father);
}
orderGenes(g){
if(g.ag1 == "ag" && g.ag2 == "Ag"){ g.ag1 = "Ag"; g.ag2 = "ag"; }
if(g.lm1 == "lm" && g.lm2 == "Lm^t"){ g.lm1 = "Lm^t"; g.lm2 = "lm"; }
if(g.lm1 == "lm" && g.lm2 == "Lm^l"){ g.lm1 = "Lm^l"; g.lm2 = "lm"; }
...