import { createMemo, createSignal } from "solid-js"; const PLOT_W = 520; const PLOT_H = 280; const PAD_X = 48; const PAD_Y = 24; const MAX_TIME = 12; function round(value: number, digits = 2) { const p = 10 ** digits; return Math.round(value * p) / p; } function format(value: number, unit = "") { const n = round(value, 2); return `${Number.isInteger(n) ? n : n.toFixed(2)}${unit}`; } function normalize(value: number, min: number, max: number) { if (Math.abs(max - min) < 1e-9) return 0.5; return (value - min) / (max - min); } export default function MotionLab() { const [initialVelocity, setInitialVelocity] = createSignal(2); const [acceleration, setAcceleration] = createSignal(1.2); const [time, setTime] = createSignal(6); const finalVelocity = createMemo( () => initialVelocity() + acceleration() * time() ); const displacement = createMemo( () => initialVelocity() * time() + 0.5 * acceleration() * time() * time() ); const samples = createMemo(() => { const points = []; for (let t = 0; t <= MAX_TIME; t += 0.2) { const v = initialVelocity() + acceleration() * t; const s = initialVelocity() * t + 0.5 * acceleration() * t * t; points.push({ t, v, s }); } return points; }); const yRange = createMemo(() => { const allV = samples().map((p) => p.v); const allS = samples().map((p) => p.s); const min = Math.min(...allV, ...allS, 0); const max = Math.max(...allV, ...allS, 0); return { min, max }; }); const toX = (t: number) => PAD_X + (t / MAX_TIME) * (PLOT_W - PAD_X * 2); const toY = (y: number) => PAD_Y + (1 - normalize(y, yRange().min, yRange().max)) * (PLOT_H - PAD_Y * 2); const velocityPath = createMemo( () => samples() .map((p, i) => `${i === 0 ? "M" : "L"} ${toX(p.t)} ${toY(p.v)}`) .join(" ") ); const displacementPath = createMemo( () => samples() .map((p, i) => `${i === 0 ? "M" : "L"} ${toX(p.t)} ${toY(p.s)}`) .join(" ") ); return (

Motion lab: velocity-time and displacement-time

setInitialVelocity(Number(e.currentTarget.value))} />
setAcceleration(Number(e.currentTarget.value))} />
setTime(Number(e.currentTarget.value))} />
v = u + at {format(finalVelocity(), " m s⁻¹")}
s = ut + 1/2at² {format(displacement(), " m")}
Direction now {finalVelocity() > 0 ? "right" : finalVelocity() < 0 ? "left" : "instant rest"}
t y
); }