JSFiddle - React, Tailwind, and code Playground

HTML

Page<br>
<canvas id=page width=64 height=64 style="width:256px"></canvas><br>
Cache<br>
<canvas id=cache width=32 height=32 style="width:128px"></canvas><br>
<input type=text id=x value=0> <input type=text id=y value=0>

CSS

canvas {
  image-rendering: -moz-crisp-edges;
  image-rendering: pixelated;
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  -khtml-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  -o-user-select: none;
  user-select: none;

}

JavaScript

// Horrific code follows, do not read.

const page = document.getElementById("page");
const pCtx = page.getContext("2d");
const cache = document.getElementById("cache");
const cCtx = cache.getContext("2d");

// Fill page with random data; different color for each block
function rand(min, max) {
    return Math.floor(Math.random() * (max - min + 1)) + min;
}
const pageData = pCtx.createImageData(64, 64);
const data = pageData.data
for (let y = 0; y != 32; y += 1) {
	for (let x = 0; x != 32; x += 1) {
  	data[4*(y * 64 + x)] = rand(200,255);
    data[4*(y * 64 + x)+1] = rand(0,80);
    data[4*(y * 64 + x)+2] = rand(0,80);
    data[4*(y * 64 + x)+3] = 255;
  }
}
for (let y = 32; y != 64; y += 1) {
	for (let x = 0; x != 32; x += 1) {
  	data[4*(y * 64 + x)] = rand(0,80);
    data[4*(y * 64 + x)+1] = rand(200,255);
    data[4*(y * 64 + x)+2] = rand(0,80);
    data[4*(y * 64 + x)+3] = 255;
  }
}
for (let y = 0; y != 32; y += 1) {
	for (let x = 32; x != 64; x += 1) {
  	data[4*(y * 64 + x)] = rand(200,255);
    data[4*(y * 64 + x)+1] = rand(200,255);
    data[4*(y * 64 + x)+2] = rand(0,80);
    data[4*(y * 64 + x)+3] = 255;
  }
}
for (let y = 32; y != 64; y += 1) {
	for (let x = 32; x != 64; x += 1) {
  	data[4*(y * 64 + x)] = rand(0,80);
    data[4*(y * 64 + x)+1] = rand(0,80);
    data[4*(y * 64 + x)+2] = rand(200,255);
    data[4*(y * 64 + x)+3] = 255;
  }
}
pCtx.putImageData(pageData, 0, 0);

// Fill cache with black
const cacheData = cCtx.getImageData(0, 0, 32, 32);
for (let y = 0; y != 32; y += 1) {
	for (let x = 0; x != 32; x += 1) {
  	cacheData.data[4*(y * 32 + x)] = 0;
    cacheData.data[4*(y * 32 + x)+1] = 0;
    cacheData.data[4*(y * 32 + x)+2] = 0;
    cacheData.data[4*(y * 32 + x)+3] = 255;
  }
}
cCtx.putImageData(cacheData, 0, 0);

function getMousePos(canvas, evt) {
  var rect = canvas.getBoundingClientRect();
  return {
    x: (evt.clientX - rect.left)>>2,
    y: (evt.clientY - rect.top)>>2
  };
}

const xInput = document.getElementById("x");
const...