Skip to content

Instantly share code, notes, and snippets.

@wking-io
Created October 23, 2025 12:29
Show Gist options
  • Select an option

  • Save wking-io/17e76627004ad5d6451d06e093973efc to your computer and use it in GitHub Desktop.

Select an option

Save wking-io/17e76627004ad5d6451d06e093973efc to your computer and use it in GitHub Desktop.
Isometric Cube in Canvas2D
import type {CubeColorValue} from "../color";
import * as Point2D from "../point-2d";
import { getProjectionDimensions, toIso } from "./utils";
export type CubeData = {
position: Point2D.Point2D;
size: number;
height: number;
color: CubeColorValue;
};
type Face = [
Point2D.Point2D,
Point2D.Point2D,
Point2D.Point2D,
Point2D.Point2D,
];
export class IsometricCube {
position: Point2D.Point2D;
size: CubeData["size"];
height: CubeData["height"];
color: CubeData["color"];
constructor(data: CubeData) {
this.position = data.position;
this.size = data.size;
this.height = data.height;
this.color = data.color;
}
render(ctx: CanvasRenderingContext2D, offset: Point2D.Point2D) {
const { position, size, height, color } = this;
// Calculate isometric projection
const projection = getProjectionDimensions(size);
const iso = toIso(position, projection, offset);
// Define the tile's vertices
const topVertices: Face = [
Point2D.create({ x: iso.x, y: iso.y - height }),
Point2D.create({
x: iso.x + projection.width,
y: iso.y + projection.height - height,
}),
Point2D.create({ x: iso.x, y: iso.y + size - height }),
Point2D.create({
x: iso.x - projection.width,
y: iso.y + projection.height - height,
}),
];
const leftSideVertices: Face = [
Point2D.create({
x: iso.x - projection.width,
y: iso.y + projection.height,
}),
Point2D.create({ x: iso.x, y: iso.y + size }),
Point2D.create({ x: iso.x, y: iso.y + size - height }),
Point2D.create({
x: iso.x - projection.width,
y: iso.y + projection.height - height,
}),
];
const rightSideVertices: Face = [
Point2D.create({
x: iso.x + projection.width,
y: iso.y + projection.height,
}),
Point2D.create({
x: iso.x + projection.width,
y: iso.y + projection.height - height,
}),
Point2D.create({ x: iso.x, y: iso.y + size - height }),
Point2D.create({ x: iso.x, y: iso.y + size }),
];
ctx.strokeStyle = color.stroke;
ctx.lineWidth = size < 16 ? 0.5 : 1;
this.drawFace(ctx, rightSideVertices, color.right);
this.drawFace(ctx, topVertices, color.top);
this.drawFace(ctx, leftSideVertices, color.left);
}
private drawFace(ctx: CanvasRenderingContext2D, face: Face, color: string) {
ctx.fillStyle = color;
ctx.beginPath();
ctx.moveTo(face[0].x, face[0].y);
face.slice(1).forEach(({ x, y }) => ctx.lineTo(x, y));
ctx.closePath();
ctx.fill();
ctx.stroke();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment