JSFiddle - React, Tailwind, and code Playground

by djwelsh

HTML

<canvas id="c" width="400" height="400"></canvas>
<canvas id="draft" width="400" height="400"></canvas>
<div id="debug"></div>

CSS

#c {
    outline: 1px solid #ccc;
    width: 400px;
    height: 400px;
    margin: 10px;
}
#draft {
    display: none;
}

JavaScript

/* Trying to make a Google Maps-style app.
 * On advice of SO answer am now trying a dual-canvas solution.
 */
var canvas, ctx, draft_canvas, draft_ctx, colorOffset;
var c_width, c_height;
var draft_img = new Image();

var globalPan = { startX : 0, startY : 0, currentX : 0, currentY : 0 };
var mouse = { x : 0, y : 0 };
var globalZoom = 1.0;
var globalRotate = 30;
var isPanning = false;

function draw() {
    draft_ctx.clearRect(0,0,c_width,c_height);
    
    draft_ctx.save();
    
    
    //Update for panning and zoom
    draft_ctx.scale(globalZoom, globalZoom);
    draft_ctx.translate(
      globalPan.currentX / globalZoom, 
      globalPan.currentY / globalZoom
    );
    
    
    //Draw shapes
    
    //Bounding box; all drawings are contained herewithin
    draft_ctx.strokeStyle = "#333";
    draft_ctx.strokeRect(0,0,c_width,c_height);
    
    //Circles
    
    //Color is just to show that we are animating
    colorOffset = (new Date()).getSeconds() * 20;
    for (var i = 12; i > 0; i--) {
        draft_ctx.beginPath();
        draft_ctx.strokeStyle = "hsl(" + (30 * i + colorOffset) + ", 100%, 50%)";
        draft_ctx.arc(200,200,10 * i, 0, Math.PI * 2, false);
        draft_ctx.stroke();
    }
    
    //Reset context so it doesn't keep translating and zooming endlessly
    draft_ctx.restore();
    
    ctx.clearRect(0,0,c_width,c_height);
    draft_img.src = draft_canvas.toDataURL();
    ctx.drawImage(
        draft_img,
        0,//-globalPan.currentX,
        0,//-globalPan.currentY,
        c_width / globalZoom,
        c_height / globalZoom,
        0,
        0,
        c_width,
        c_height
    );
    
    //Debugging stuff
    debug.innerHTML = "globalPan.startX: " + globalPan.startX
         + "<br>globalPan.startY: " + globalPan.startY
         + "<br>globalPan.currentX: " + globalPan.currentX
         + "<br>globalPan.currentY: " + globalPan.currentY
         + "<br>mouse x: " + mouse.x
         + "<br>mouse y: " + mouse.y
         +...