JSFiddle - React, Tailwind, and code Playground
by Gwyn Milcote
HTML
Testing all animal genes and images here. Punnett square at the bottom.
<p>
<span id='overall_stats'></span>
<br><span id='species_stats'></span>
<br>Refresh the page for a different animal!
</p>
<select id='animal_types'>
<option disabled>--- Mammals</option>
<option value='cat' selected>Cat</option>
<option value='dog'>Dog</option>
<option value='horse'>Horse</option>
<option value='donkey'>Donkey</option>
<option value='cow'>Cow</option>
<option value='pig'>Pig</option>
<option value='mouse'>Mouse</option>
<option value='rat'>Rat</option>
<option value='cavy'>Guinea pig</option>
<option value='rabbit'>Rabbit</option>
<option value='ferret'>Ferret</option>
<option value='fox'>Fox</option>
<option disabled>--- Birds</option>
<option value='chicken'>Chicken (colour)</option>
<option value='chicken2'>Chicken (shape)</option>
<option value='pigeon'>Pigeon</option>
<option value='budgie'>Budgie</option>
<option value='cockatiel'>Cockatiel</option>
<option value='zebrafinch'>Zebra finch</option>
<option value='bengalese'>Bengalese finch</option>
<option value='quail1'>Quail (Japanese)</option>
<option value='quail2'>Quail (Chinese Painted)</option>
<option value='quail3'>Quail (Bobwhite)</option>
<option disabled>--- Reptiles</option>
<option value='cornsnake'>Corn snake</option>
<option value='ballpython'>Ball python</option>
<option value='reticpython'>Reticulated python</option>
<option disabled>--- Fish</option>
<option value='goldfish'>Goldfish</option>
<option value='medaka'>Medaka</option>
<option value='zebrafish'>Zebrafish</option>
</select>
<button id='random_animal'>Randomise!</button>
<button id='cross_animal'>Cross 2 random parents</button>
<p>JSON: <span id='json_geno'>...</span></p>
Geno: <span id='output_geno' class='genotype_display'>...</span>
<p>Image: <div id='animal_image'>...</div></p>
Generating dropdowns...
CSS
img, div, button, p, span {
box-sizing: border-box;
}
.genotype_display .alleles {
display: inline-block;
padding: 5px;
border: 1px solid silver;
cursor: pointer;
position: relative;
}
.genotype_display .modifier {
display: inline-block;
padding: 5px;
border: 1px solid silver;
}
.tooltip {
display: none;
position: absolute;
top: 120%;
left: calc(50% - 40px);
border: 1px solid silver;
background-color: #fff;
padding: 10px;
z-index: 2;
}
.section {
border: 1px solid silver;
padding: 10px;
margin: 20px auto;
}
#select_container {
display: flex;
flex-flow: row wrap;
}
#select_container .select_holder {
padding: 2px;
width: 50%;
border: 1px solid #eee;
}
/* PUNNETT SQUARE */
#punnett_table table {
width: 100%;
margin: 20px 0px;
border-collapse: collapse;
}
#punnett_table table td {
border: 1px solid grey;
padding: 5px;
text-align: center;
}
#punnett_table .cell_m {
background-color: #E8F6FC;
}
#punnett_table .cell_f {
background-color: #FCE8F5;
}
/* Other styles like paint/tortie? */
/* GENERAL */
.father_bg {
background-color: powderblue;
}
.mother_bg {
background-color: lightpink;
}
.bold {
font-weight: bold;
}
/* COAT IMAGES */
.animal_coat {
position: relative;
}
.animal_coat img {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
.coat_full {
width: 500px;
height: 400px;
}
.coat_half {
width: 250px;
height: 200px;
}
/* FILTERS */
/* Shared across all animals */
.f_black { filter: invert(90%); }
.f_grey { filter: invert(50%); }
.f_silver { filter: invert(80%); }
.f_white { filter: invert(100%); }
.f_brown { filter: invert(65%) sepia(80%) saturate(272%) hue-rotate(337deg) brightness(98%) contrast(94%); }
.f_chocolate { filter: invert(32%) sepia(98%) saturate(815%) hue-rotate(355deg) brightness(89%) contrast(92%); }
.f_pink { filter: invert(85%) sepia(10%)...
JavaScript
const path = "http://mythstable.epizy.com/genetic/images/";
/*
* For assembling image layers, storing HTML.
*
* let c = new Coat(a, "thumb");
* c.addFilter("base", baseCSS);
* c.addImage("pangare", 0.5);
* c.addImage("roan");
* c.endCoat();
* let html = c.output();
*/
class Coat {
constructor(path, size = ""){
this.path = path;
this.startCoat();
}
startCoat(){
this.html = "";
}
// For fixed images.
addImage(url, opacity = 1){
this.html += "<img src='" + this.path + url + ".png'";
if(opacity < 1){
this.html += " style='opacity:" + opacity + "'";
}
this.html += ">\n";
}
// For black PNGs to be recoloured.
addFilter(url, css, opacity = 1){
this.html += "<img src='" + this.path + url + ".png' class='f_" + css + "'";
if(opacity < 1){
this.html += " style='opacity:" + opacity + "'";
}
this.html += ">\n";
}
endCoat(){
this.html += "<img src='" + this.path + "line.png'>\n";
}
output(){
return this.html;
}
}
/*
* All data and animal-specific funcs here.
* GENOME object contains loci + alleles, ordered by dominance.
* TERMS array will be mapped. {adultMale: "stallion"} etc.
* getPath() sets up the path for image URLs.
* getImage() returns image HTML and description array.
*/
const D = {
horse: {
name: "Horse", specific: "Equus ferus caballus",
genome: {
e: {
name: "Extension", wt: "E+",
alleles: ["E+", "e"]
},
a: {
name: "Agouti", wt: "A+",
alleles: ["A+", "a^t", "a"]
},
cr: {
name: "Cream", wt: "cr+",
alleles: ["Cr", "cr+", "prl"]
},
ch: {
name: "Champagne", wt: "ch+",
alleles: ["Ch", "ch+"]
},
g: {
...