JSFiddle - React, Tailwind, and code Playground

HTML

<button onclick="Logo.forward(10)">Move forward 10</button>
<button onclick="Logo.forward(50)">Move forward 50</button>
<button onclick="Logo.rotate(15)">Rotate Right (15 deg)</button>
<button onclick="Logo.rotate(-15)">Rotate Left (-15 deg)</button>
<button onclick="Logo.rotate(90)">Turn Right (90 deg)</button>
<button onclick="Logo.rotate(-90)">Turn Left (-90 deg)</button>
<button onclick="Logo.changeColor('red')">Color Red</button>
<button onclick="Logo.changeColor('blue')">Color Blue</button>
<button onclick="Logo.changeColor('white')">Color White</button>
<button onclick="Nyan()">NYAN!</button>
<button onclick="Nyan(true)">Benchmark NYAN!</button>
<button onclick="Logo.reset()">Reset</button>
<div>
    <canvas width="500" height="500" id="drawSurface"></canvas>
    <canvas width="500" height="500" id="cursor"></canvas>
</div>
    
<img id="cat" style="display: none;" src=...

CSS

#drawSurface {
    margin: 10px 10px -500px 10px;
    box-shadow: 0 0 5px;  
    border: 1px solid black;    
}

#cursor {
    margin: 0 10px;
    position: relative;
    top: -6px;
    border: 1px solid black;   
}

JavaScript

window.Logo = (function(fps, canvasId, cursorId, catId) {
    var catImg = document.getElementById(catId),
        canvas = document.getElementById(canvasId),
        cursor = document.getElementById(cursorId),
        ctx = canvas.getContext('2d'),
        curCtx = cursor.getContext('2d'),
        delay = 1000 / fps,
        completeFns = [],
        queue = []
    ;
    
    var init = function () {
        ctx.strokeStyle = "white";
        ctx.fillColor = "black"; 
        ctx.lineWidth = 4; 
        ctx.fillRect(0, 0, canvas.width, canvas.height); 
        ctx.translate((canvas.width/2), (canvas.height/2));
        curCtx.translate((canvas.width/2), (canvas.height/2));
        curCtx.moveTo(0, 0);
        ctx.beginPath();
        ctx.moveTo(0, 0);
        
        draw(); //begin draw loop  
    };
    
    var draw = function () {
        var i, next;
        
        curCtx.clearRect(-50,-50,100,100);
        
        if(queue.length > 0) { //pop next step from queue
            next = queue.splice(0, 1)[0];
            drawFns[next.type](next.val);
        } 
        
        curCtx.drawImage(catImg, 0, -9); //draw Nayncat.
        
        if(queue.length === 0 && completeFns.length > 0) {
            for(i=0; i<completeFns.length; i++) {
                completeFns[i]();   
            }
            completeFns = [];
        }
        
        setTimeout(draw, delay);
    };
    
    var forward = function (dist, speed) {
        speed = speed || 1;
        var i, dir = (dist >= 0) ? speed : -speed;
        
        for(i=0; i<Math.abs(dist); i+=speed) {
            queue.push({
                type: "forward",
                val: dir
            });             
        }
    };
    
    var drawFns = {
        rotate: (function(val) { 
            ctx.rotate(val, 0);
            curCtx.rotate(val, 0);
        }),
        forward: (function(val) {
            ctx.lineTo(val, 0);
            ctx.stroke();
            ctx.translate(val, 0);
           ...