UNPKG

@sirhc77/canvas-math-kit

Version:

A lightweight, interactive canvas-based vector visualizer for math, linear algebra, and ML education. Built with React + TypeScript.

114 lines (113 loc) 3.24 kB
export function toCanvas(x, y, origin, scale) { return { x: origin.x + x * scale, y: origin.y - y * scale, }; } export function drawGrid(ctx, width, height, scale) { ctx.save(); ctx.strokeStyle = '#eee'; ctx.lineWidth = 1; const originX = width / 2; const originY = height / 2; const startX = -Math.floor(originX / scale); const endX = Math.ceil((width - originX) / scale); const startY = -Math.floor(originY / scale); const endY = Math.ceil((height - originY) / scale); for (let i = startX; i <= endX; i++) { const x = originX + i * scale; ctx.beginPath(); ctx.moveTo(x, 0); ctx.lineTo(x, height); ctx.stroke(); } for (let j = startY; j <= endY; j++) { const y = originY - j * scale; ctx.beginPath(); ctx.moveTo(0, y); ctx.lineTo(width, y); ctx.stroke(); } ctx.restore(); } export function drawAxes(ctx, width, height, origin) { ctx.save(); ctx.strokeStyle = '#999'; ctx.lineWidth = 2; // X-axis ctx.beginPath(); ctx.moveTo(0, origin.y); ctx.lineTo(width, origin.y); ctx.stroke(); // Y-axis ctx.beginPath(); ctx.moveTo(origin.x, 0); ctx.lineTo(origin.x, height); ctx.stroke(); ctx.restore(); } export function drawLine(ctx, from, to, color, lineWidth) { ctx.save(); ctx.strokeStyle = color; ctx.lineWidth = lineWidth; ctx.beginPath(); ctx.moveTo(from.x, from.y); ctx.lineTo(to.x, to.y); ctx.stroke(); ctx.restore(); } export function drawArrowhead(ctx, from, to, color) { const headLength = 10; // size in logical pixels const dx = to.x - from.x; const dy = to.y - from.y; const angle = Math.atan2(dy, dx); ctx.save(); ctx.fillStyle = color; ctx.beginPath(); ctx.moveTo(to.x, to.y); ctx.lineTo(to.x - headLength * Math.cos(angle - Math.PI / 6), to.y - headLength * Math.sin(angle - Math.PI / 6)); ctx.lineTo(to.x - headLength * Math.cos(angle + Math.PI / 6), to.y - headLength * Math.sin(angle + Math.PI / 6)); ctx.closePath(); ctx.fill(); ctx.restore(); } export function drawCircle(ctx, center, radius, color) { ctx.save(); ctx.beginPath(); ctx.arc(center.x, center.y, radius, 0, 2 * Math.PI); ctx.fillStyle = color; ctx.fill(); ctx.restore(); } export function drawParallelogram(ctx, p0, p1, p2, p3, fillColor, strokeColor) { ctx.save(); if (fillColor) { ctx.fillStyle = fillColor; } if (strokeColor) { ctx.strokeStyle = strokeColor; ctx.lineWidth = 2; } ctx.beginPath(); ctx.moveTo(p0.x, p0.y); ctx.lineTo(p1.x, p1.y); ctx.lineTo(p2.x, p2.y); ctx.lineTo(p3.x, p3.y); ctx.closePath(); if (fillColor) ctx.fill(); if (strokeColor) ctx.stroke(); ctx.restore(); } export function writeLabel(ctx, text, x, y, font = '16px Arial', color = '#333', textAlign = 'left', textBaseline = 'middle') { if (ctx) { ctx.save(); ctx.font = font; ctx.fillStyle = color; ctx.textAlign = textAlign; ctx.textBaseline = textBaseline; ctx.fillText(text, x, y); ctx.restore(); } }