From df8e29c6e36d850f70f34724f45cfe1983d9da9b Mon Sep 17 00:00:00 2001 From: "F.W. Dekker" Date: Sun, 31 Oct 2021 16:14:57 +0100 Subject: [PATCH] Add basic non-adaptive zooming --- src/main/js/Main.ts | 64 +++++++++++++++++++++++++++++++++------------ 1 file changed, 47 insertions(+), 17 deletions(-) diff --git a/src/main/js/Main.ts b/src/main/js/Main.ts index 4be2a35..726a850 100644 --- a/src/main/js/Main.ts +++ b/src/main/js/Main.ts @@ -109,47 +109,62 @@ class Line { } +/** + * Global constants. + */ +const settings = { + dotRadius: 10, + stepTime: 250, + stepsPerLevel: 5, +}; + + +// Unhide main element doAfterLoad(() => $("main").classList.remove("hidden")); +// Application loop(s) doAfterLoad(() => { const canvas = $("#art"); const ctx = canvas.getContext("2d"); - // State - const lines: Line[] = [new Line(1), new Line(2)]; + + // Model + const lines: Line[] = [new Line(1), new Line(5)]; let step = 0; setInterval(() => { - const stepLine = Math.floor(step / 25); + const stepLine = Math.floor(step / (settings.stepsPerLevel ** 2)); const inductionLine = stepLine + 1; const superInductionLine = stepLine + 2; // Add new low-level segment - const length = 5 ** (2 + stepLine); + const length = settings.stepsPerLevel ** (2 + stepLine); + // TODO: Accumulate angles const angle = (random_normal() - 0.5) * Math.PI * 2; lines[stepLine].segments.push(new LineSegment(Math.cos(angle) * length, Math.sin(angle) * length)); // Add first-level induction line - if ((step + 1) % 5 === 0) { + if ((step + 1) % settings.stepsPerLevel === 0) { if (lines.length <= inductionLine) { - lines[inductionLine] = new Line(inductionLine + 1); + lines[inductionLine] = new Line(5 ** inductionLine); } - lines[inductionLine].segments.push(lines[stepLine].sumSegmentsSlice(-5)); + lines[inductionLine].segments.push(lines[stepLine].sumSegmentsSlice(-settings.stepsPerLevel)); } // Add second-level induction line - if ((step + 1) % 25 === 0) { + if ((step + 1) % (settings.stepsPerLevel ** 2) === 0) { if (lines.length <= superInductionLine) { - lines[superInductionLine] = new Line(superInductionLine + 1); + lines[superInductionLine] = new Line(5 ** superInductionLine); } - lines[superInductionLine].segments.push(lines[inductionLine].sumSegmentsSlice(-5)); + lines[superInductionLine].segments.push(lines[inductionLine].sumSegmentsSlice(-settings.stepsPerLevel)); } step++; - }, 250); + }, settings.stepTime); + // Resize const resize = () => { @@ -159,28 +174,42 @@ doAfterLoad(() => { window.addEventListener("resize", resize, false); resize(); + // Draw + const startTime = Date.now(); const draw = () => { - const center = new Point(canvas.width / 2, canvas.height / 2); + ctx.restore(); + ctx.save(); // Background ctx.fillStyle = "#000000"; ctx.fillRect(0, 0, canvas.width, canvas.height); + // Draw from center + const center = new Point(canvas.width / 2, canvas.height / 2); + ctx.translate(center.x, center.y); + // Center dot ctx.beginPath(); - ctx.fillStyle = "#ffffff"; - ctx.arc(center.x - 5, center.y - 5, 10, 0, 2 * Math.PI); - ctx.fill(); + ctx.strokeStyle = "#ffffff"; + ctx.arc(0, 0, settings.dotRadius, 0, 2 * Math.PI); + ctx.stroke(); + + // Zoom + // TODO: Adaptive zoom + const nowTime = Date.now(); + const factor = settings.stepsPerLevel ** + ((nowTime - startTime) / (settings.stepsPerLevel ** 2 * settings.stepTime)); + ctx.scale(1 / factor, 1 / factor); // Lines ctx.strokeStyle = "#ffffff"; for (const line of lines) { ctx.lineWidth = line.thickness; ctx.beginPath(); - ctx.moveTo(center.x, center.y); + ctx.moveTo(0, 0); - let lastPos = new Point(center.x, center.y); + let lastPos = new Point(0, 0); for (const segment of line.segments) { lastPos = new Point(lastPos.x + segment.x, lastPos.y + segment.y); ctx.lineTo(lastPos.x, lastPos.y); @@ -189,6 +218,7 @@ doAfterLoad(() => { ctx.stroke(); } + // Repeat window.requestAnimationFrame(draw); }; window.requestAnimationFrame(draw);