JSFiddle - React, Tailwind, and code Playground
by Josh Pullen
CSS
canvas {
border: 1px solid black;
max-width: calc(100vw - 20px);
max-height: calc(100vh - 20px);
}
JavaScript
const canvas = document.createElement("canvas");
const ctx = canvas.getContext("2d");
function drawGrid() {
ctx.beginPath();
for (let x = -3; x <= 3; x++) {
ctx.moveTo(x, -100);
ctx.lineTo(x, 100);
}
for (let y = -3; y <= 3; y++) {
ctx.moveTo(-100, y);
ctx.lineTo(100, y);
}
ctx.strokeStyle = "#ddd";
ctx.lineWidth = 0.02;
ctx.stroke();
}
function drawFunction(f) {
ctx.beginPath();
ctx.moveTo(-4, f(-4));
for (let x = -4; x <= 4; x += 0.05) {
ctx.lineTo(x, f(x));
}
ctx.strokeStyle = "black";
ctx.lineWidth = 0.05;
ctx.stroke();
}
function drawHeatmap(f) {
const imgData = ctx.createImageData(canvas.width, canvas.height);
for (let x = 0; x < canvas.width; x++) {
for (let y = 0; y < canvas.height; y++) {
const value = f(x, y);
imgData[(x + y * canvas.height) * 4 + 0] = value;
imgData[(x + y * canvas.height) * 4 + 1] = value;
imgData[(x + y * canvas.height) * 4 + 2] = value;
imgData[(x + y * canvas.height) + 3] = 255;
}
}
ctx.putImageData(imgData, 0, 0);
}
function render() {
drawGrid();
// Moving point
/* ctx.beginPath();
ctx.arc(0, 0, 1, 0, 2 * Math.PI)
ctx.fill(); */
// Function
drawFunction(x => Math.sin(x));
drawFunction(x => Math.sin(x + 1));
drawFunction(x => Math.sin(x + 2));
drawFunction(x => Math.sin(x + 3));
drawFunction(x => Math.sin(x + 4));
drawFunction(x => Math.sin(x + 5));
// Heatmap
drawHeatmap((x, y) => {
return x + y;
});
}
/*
Common patterns:
- Start with one of something, then manually create many of them, then automatically create many
*/
canvas.width = 640;
canvas.height = 480;
document.body.appendChild(canvas);
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.translate(canvas.width / 2, canvas.height / 2);
ctx.scale(100, -100);
render(canvas, ctx);