Sign in

Search issue titles and bodies, change requests and comments. Private repositories you cannot read are not included.

vole
Clone

Read only, no credentials:

https://rodent.software/vole.git

Write over SSH with a registered key:

git clone ssh://git@rodent.software:2222/vole.git

A free and open-source forge that lives in your Git repo.

Use the library's realistic-look and fireworks examples for the burst

5946444571d7784252b131623cd15679adabe18f · Keenan Nemetz · 13d ago · parent 6b7d6a18

Use the library's realistic-look and fireworks examples for the burst

120 particles at scalar 1 from one point read as a small puff on a full-width
page. The opening burst is now canvas-confetti's "realistic look" preset — 500
particles, spread 180, ticks 400, gravity 0.5, decay 0.92, startVelocity 30 and
scalar 1.2 — followed by its "fireworks" volley from both edges, tapering over
1.2s instead of the example's 15: the page this lands on is one you are about to
read, not a celebration screen.

Measured in a headless Firefox at 1360x682 after a real Merge click: 181 frames
over 3s, median 17ms, p95 20ms, worst 23ms, so it holds 60fps while it runs, and
the canvas is gone by the time the burst is over — the volley's timer ends with
it rather than lingering.

Refs #01M5Z00VJ6215NFZ8F3KJ48FXA

server/web/static/app.js +32−6

@@ -350,7 +350,15 @@ const copyText = (value, done) => {
350 350 // worker — but the library hands its canvas to the worker anyway, transferring it
351 351 // with transferControlToOffscreen, and then draws nothing: the canvas is present
352 352 // and permanently empty, with no error to see. An instance that draws on the main
353 // thread costs 120 particles for ~2s, which is nothing, and needs no CSP change.
353 // thread costs a few hundred particles for a few seconds, which is nothing, and
354 // needs no CSP change.
355 //
356 // The numbers are two of the library's own examples. The opening burst is the
357 // "realistic look" preset: more particles, a wider spread, a longer life, lower
358 // gravity and scalar > 1, which is what stops it reading as a small puff. The
359 // volley that follows is the "fireworks" preset from both edges, cut from fifteen
360 // seconds to just over one, because the page this lands on is one you are about to
361 // read. Together they are under a thousand particles.
354 362 (() => {
355 363 const params = new URLSearchParams(window.location.search);
356 364 if (!params.has('merged')) return;
@@ -364,12 +372,30 @@ const copyText = (value, done) => {
364 372 script.onload = () => {
365 373 if (typeof window.confetti !== 'function') return;
366 374 const burst = window.confetti.create(null, { resize: true, useWorker: false });
367 burst({
368 particleCount: 120,
369 spread: 70,
370 origin: { x: 0.5, y: 0.6 },
375 const look = {
376 startVelocity: 30,
377 spread: 180,
378 ticks: 400,
379 gravity: 0.5,
380 decay: 0.92,
381 scalar: 1.2,
371 382 disableForReducedMotion: true,
372 });
383 };
384
385 // The "realistic look" burst.
386 burst({ ...look, particleCount: 500, origin: { x: 0.5, y: 0.6 } });
387
388 // The "fireworks" volley, from both edges, tapering as the clock runs out.
389 const volleyMs = 1200;
390 const end = Date.now() + volleyMs;
391 (function frame() {
392 const left = end - Date.now();
393 if (left <= 0) return;
394 const particleCount = 30 * (left / volleyMs);
395 burst({ ...look, particleCount, angle: 60, spread: 55, origin: { x: 0 } });
396 burst({ ...look, particleCount, angle: 120, spread: 55, origin: { x: 1 } });
397 setTimeout(frame, 250);
398 })();
373 399 };
374 400 document.head.appendChild(script);
375 401 })();