JSFiddle - React, Tailwind, and code Playground
by Rajesh Danabal
HTML
<canvas id="canvas" width="800" height="600" style="border:1px solid #ccc;"></canvas>
JavaScript
class ViewTransform {
constructor() {
this.scale = 1;
this.offsetX = 0;
this.offsetY = 0;
}
transformX(x) {
return x * this.scale + this.offsetX;
}
transformY(y) {
return y * this.scale + this.offsetY;
}
inverseX(screenX) {
return (screenX - this.offsetX) / this.scale;
}
inverseY(screenY) {
return (screenY - this.offsetY) / this.scale;
}
pan(dx, dy) {
this.offsetX += dx;
this.offsetY += dy;
}
zoomAt(mouseX, mouseY, zoomFactor) {
const worldX = this.inverseX(mouseX);
const worldY = this.inverseY(mouseY);
this.scale *= zoomFactor;
this.offsetX = mouseX - worldX * this.scale;
this.offsetY = mouseY - worldY * this.scale;
}
}
class Shape {
constructor(x, y) {
this.x = x;
this.y = y;
}
}
class Rect extends Shape {
constructor(x, y, w, h, color = 'blue') {
super(x, y);
this.w = w;
this.h = h;
this.color = color;
}
draw(ctx, vt) {
ctx.fillStyle = this.color;
ctx.fillRect(
vt.transformX(this.x),
vt.transformY(this.y),
this.w * vt.scale,
this.h * vt.scale
);
}
}
class Line {
constructor(x1, y1, x2, y2, color = 'black') {
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
this.color = color;
}
draw(ctx, vt) {
ctx.strokeStyle = this.color;
ctx.beginPath();
ctx.moveTo(vt.transformX(this.x1), vt.transformY(this.y1));
ctx.lineTo(vt.transformX(this.x2), vt.transformY(this.y2));
ctx.stroke();
}
}
class Layer {
constructor() {
this.shapes = [];
}
add(shape) {
this.shapes.push(shape);
}
draw(ctx, vt) {
this.shapes.forEach(shape => shape.draw(ctx, vt));
}
}
// Init
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
const vt = new ViewTransform();
const layers = [];
// Sample Layers
const rectLayer = new Layer();
rectLayer.add(new Rect(100, 100, 80, 50, 'tomato'));
rectLayer.add(new Rect(300, 200, 100,...