JSFiddle - React, Tailwind, and code Playground

by Gwyn Milcote

HTML

<img src='http://mythstable.epizy.com/genetic/images/chinchilla/line.png?i=1' style='width: 20%; height: auto;'>
<p>Testing canvas. There should be a bunch of coloured animals below.</p>
<div id='pet_1' class='pet_canvas canvas_thumb'></div>
<div id='pet_2' class='pet_canvas canvas_thumb'></div>
<div id='pet_3' class='pet_canvas canvas_thumb'></div>
<div id='pet_4' class='pet_canvas canvas_thumb'></div>
<div id='pet_5' class='pet_canvas canvas_thumb'></div>
<div id='pet_6' class='pet_canvas canvas_thumb'></div>
<div id='pet_7' class='pet_canvas canvas_thumb'></div>
<div id='pet_8' class='pet_canvas canvas_thumb'></div>
<div id='pet_9' class='pet_canvas canvas_thumb'></div>
<div id='pet_10' class='pet_canvas canvas_thumb'></div>
<div id='pet_11' class='pet_canvas canvas_thumb'></div>
<div id='pet_12' class='pet_canvas canvas_thumb'></div>
<div id='pet_13' class='pet_canvas canvas_thumb'></div>
<div id='pet_14' class='pet_canvas canvas_thumb'></div>
<div id='pet_15' class='pet_canvas canvas_thumb'></div>
<div id='pet_16' class='pet_canvas canvas_thumb'></div>
<div id='pet_17' class='pet_canvas canvas_thumb'></div>
<div id='pet_18' class='pet_canvas canvas_thumb'></div>
<div id='pet_19' class='pet_canvas canvas_thumb'></div>
<div id='pet_20' class='pet_canvas canvas_thumb'></div>


<h2>Canvas vs CSS</h2>
<p>If you're making a dress-up doll game, or custom product designer, or virtual pet game where the animals have layers of markings in different colours, both of these approaches can work. They allow similar things:</p>

<ul>
    <li>Layer transparent PNG images on top of each other.</li>
    <li>Stretch or scale images up or down.</li>
    <li>Position images exactly (by percentage or pixel).</li>
    <li>Recolour an image, using hex/RGB/etc or a CSS filter class.</li>
    <li>Change opacity of certain layers.</li>
    <li>Layer effects such as Multiply, Overlay etc.</li>
    <li>Masks etc. Fill areas with pattern images, or cut out to be...

CSS

div, img {box-sizing:border-box;}
body {
    background: silver;
}

table {
    border-collapse: collapse;
}
table td, table th {
    padding: 10px;
    border: 1px solid grey;
}

/* Canvases are inside divs */
canvas {width: 100%; height: 100%;}

.pet_canvas {
    border: 0px dashed teal;
    display: inline-block;
}
.canvas_full {
    width: 500px;
    height: 400px;
}
.canvas_thumb {
    width: 250px;
    height: 200px;
}

JavaScript

let petPath = "http://mythstable.epizy.com/genetic/images/";

let pets = [
    {id: 1, species: "cat", base: "EBC4A4"},
    {id: 2, species: "sheep", base: "FFCC33"},
    {id: 3, species: "fox", base: "5C5248"},
    {id: 4, species: "budgie", base: "3CDEAB"},
    {id: 5, species: "goat", base: "E8D07F"},
    {id: 6, species: "mouse", base: "856D59"},
    {id: 7, species: "mink", base: "856D59"},
    {id: 8, species: "rabbit", base: "C9620E"},
    {id: 9, species: "zebrafinch", base: "5C5248"},
    {id: 10, species: "cow", base: "3CDEAB"},
    {id: 11, species: "pig", base: "E8D07F"},
    {id: 12, species: "cock", base: "856D59"},
    {id: 13, species: "dog", base: "E8D07F"},
    {id: 14, species: "ferret", base: "856D59"},
    {id: 15, species: "rat", base: "E8D07F"},
    {id: 16, species: "cavy", base: "856D59"},
    {id: 17, species: "chinchilla", base: "C9620E"},
    {id: 18, species: "hamster", base: "EBC4A4"},
    {id: 19, species: "horse", base: "FFCC33"},
    {id: 20, species: "duck", base: "FFCC33"}
];

class PetCanvas {
    
    constructor(pet, size = false){
        // Create canvas that'll fill parent div.
        this.parent = document.getElementById("pet_" + pet.id);
        this.canvas = document.createElement('canvas');
        
        // Later, when have matching-size images.
        //this.width = this.parent.offsetWidth;
        //this.height = this.parent.offsetHeight;
        
        this.ctx = this.canvas.getContext("2d");
        this.layers = [];
        this.setSize(size);
        this.path = petPath + pet.species + "/";
        this.pet = pet;
    }
    
    /*
    * Canvases look ugly, pixelated if
    * simply halve the size but use same
    * images. So use thumb-sized imgs later.
    *
    * If canvas is 100% w/h of parent div,
    * plus same size... full-size images
    * can scale down and look smooth.
    */
    setSize(s){
        // after uploading thumb imgs, may not need these
        this.width = 500;
        this.height =...