JSFiddle - React, Tailwind, and code Playground
HTML
<html>
<body>
<canvas id="canvas"></canvas>
</body>
</html>
CSS
body, html {
margin: 0;
padding: 0;
background-color: #AAAAAA;
}
JavaScript
const WIDTH = 32;
const HEIGHT = 24;
const PIXEL_SIZE = 10;
const getPosition = (i) => {
return {
x: i % WIDTH,
y: Math.floor(i / WIDTH),
};
};
const pixels = Array.from({ length: WIDTH * HEIGHT }, (_, i) => {
const { x, y } = getPosition(i);
if ((x % 2 === 0 && y % 2 === 0) || (x % 2 !== 0 && y % 2 !== 0)) {
return [204, 204, 204, 255];
}
return [255, 255, 255, 255];
}).flat();
const data = new ImageData(new Uint8ClampedArray(pixels), WIDTH, HEIGHT);
const canvas = document.getElementById("canvas");
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
const ctx = canvas.getContext("2d");
ctx.imageSmoothingEnabled = false;
const bufferCanvas = document.createElement("canvas");
bufferCanvas.width = WIDTH;
bufferCanvas.height = HEIGHT;
const bufferCtx = bufferCanvas.getContext("2d");
// controls how big the grid is
let scale = 1.5;
// controls where the grid is drawn,
// starts exactly in the middle of the screen
let originX = canvas.width / 2 - (WIDTH * PIXEL_SIZE * scale) / 2;
let originY = canvas.height / 2 - (HEIGHT * PIXEL_SIZE * scale) / 2;
let offsetX = originX;
let offsetY = originY;
function zoom(event) {
event.preventDefault();
// Get the offset relative to the canvas element
offsetX = event.x;
offsetY = event.y;
const wheel = event.deltaY < 0 ? 1 : -1;
const z = Math.exp(wheel * 0.05);
scale *= z;
// this adjusts the scale just fine-ish
// however, the origin needs to move in relation
// to the cursor position
}
window.addEventListener("wheel", zoom, { passive: false });
function animate() {
requestAnimationFrame(animate);
ctx.clearRect(0, 0, canvas.width, canvas.height);
bufferCtx.putImageData(data, 0, 0);
ctx.drawImage(
bufferCanvas,
originX - offsetX,
originY - offsetY,
WIDTH * PIXEL_SIZE * scale,
HEIGHT * PIXEL_SIZE * scale
);
}
animate();