JSFiddle - React, Tailwind, and code Playground

by Gwyn Milcote

HTML

<p>Griffin colour calculator. For 'Shrine of the Griffin'. Faded shade is not included here - I'm not sure what caused it. I assume it was a Normal-shaded griffin (no cream genes) with one or two fade alleles.</p>
<div class='center'>

<div id='mother'>Mother: <span id='parent_info_2'>Loading...</span><br>
<div id='parent_coat_2' class='griffin_coat coat_adult'>Rendering coat...</div>
<select id='f_r1'> 
    <option value='R' selected>R</option>
    <option value='r'>r</option>
</select>
<select id='f_r2'>
    <option value='R' selected>R</option>
    <option value='r'>r</option>
</select> 
<select id='f_g1'>
    <option value='G'>G</option>
    <option value='g' selected>g</option>
</select>
<select id='f_g2'>
    <option value='G'>G</option>
    <option value='g' selected>g</option>
</select>
<select id='f_cr1'>
    <option value='Cr' selected>Cr</option>
    <option value='cr'>cr</option>
</select>
<select id='f_cr2'>
    <option value='Cr'>Cr</option>
    <option value='cr' selected>cr</option>
</select>
</div> 
<div id='father'>Father: <span id='parent_info_1'>Loading...</span><br>
<div id='parent_coat_1' class='griffin_coat coat_adult'>Rendering coat...</div>
<select id='m_r1'> 
    <option value='R' selected>R</option>
    <option value='r'>r</option>
</select>
<select id='m_r2'>
    <option value='R'>R</option>
    <option value='r' selected>r</option>
</select> 
<select id='m_g1'>
    <option value='G' selected>G</option>
    <option value='g'>g</option>
</select>
<select id='m_g2'>
    <option value='G'>G</option>
    <option value='g' selected>g</option>
</select>
<select id='m_cr1'>
    <option value='Cr'>Cr</option>
    <option value='cr' selected>cr</option>
</select>
<select id='m_cr2'>
    <option value='Cr'>Cr</option>
    <option value='cr' selected>cr</option>
</select>
</div>
<br><button id='cross'>Cross</button><br>Here are the coat colours of potential offspring.<br>

<table id='result_table'></table>
</div>

CSS

.center {text-align:center;}
#mother, #father {border:1px solid black;padding:10px;margin:5px;border-radius:5px;display:inline-block;vertical-align:top;}
#muming, #dadimg {padding:5px;}

#result_table {width:100%;margin-top:10px;border-spacing:5px;}
#result_table td {font-size: 12px; border:1px solid black;border-radius:5px;padding:5px;text-align:center;}


.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_thumb {
    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 {filter: invert(60%) sepia(44%) saturate(658%) hue-rotate(340deg) brightness(90%) contrast(78%);}
.f_orange_3 {filter: invert(77%) sepia(9%) saturate(2816%) hue-rotate(340deg) brightness(97%) contrast(89%);}
.f_orange_4 {filter: invert(89%) sepia(17%)...

JavaScript

const path = 'http://mythstable.epizy.com/ootg/images/';

const colourNames = [
    ["Red", "Salmon", "Amaranth", "Pink"],
    ["Orange", "Tan", "Gold", "Cream"],
    ["Amber", "Khaki", "Chiffon", "Ivory"],
    ["Green", "Olive", "Lime", "Celadon"],
    ["Teal", "Stormy Seas", "Cyan", "Seafoam"],
    ["Cobalt Blue", "Steel Blue", "Sky Blue", "Baby Blue"],
    ["Purple", "Violet", "Amethyst", "Lavender"],
    ["Bronze", "Mocha", "Copper", "Sandy"],
    ["Oil Spill", "Opal", "Titanium", "Pearl"],
    ["Black", "Grey", "Smoke", "Silver"]
];
    
const shadeNames = ["Normal", "Faded", "Bright", "Cream"];

// For assembling image HTML.
class Coat {
    constructor(sex, stage, size = ""){
        this.path = path + stage + "/";
        if(stage > 3){ this.path += sex + "/"; }
        //if(size == "full"){ this.path += "full/"; } // 600px
        if(size == "thumb"){ this.path += "thumb/"; } // 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;
    }
}


class ColourCalc {
    constructor(){
        this.mother = {sex: 2, g1: "g", g2: "g", r1: "R", r2: "R", cr1: "Cr", cr2: "cr"};
        this.father = {sex: 1, g1: "G", g2: "g", r1: "R", r2: "r", cr1:...