The optional final polish: five refinements
The bolt deepens to saturated gold over a dark amber glow; the splash throws a wider crown of five droplets over a broader pool; the fireworks lose their protractor — uneven angles, lengths, sizes, and staggered timing, as a real burst has; the portal-cell's void gains turning swirl arms so the dark center reads as motion, not blur; the streak narrows and softens so its peak frame no longer resembles a drawn white line. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
e713d69582
commit
c6d73550df
@@ -5,24 +5,34 @@
|
||||
let { fx }: { fx: FxOf<"fireworks"> } = $props();
|
||||
const c = $derived(center(fx.at));
|
||||
const COLORS = ["#e74c3c", "#f1c40f", "#3b8dd6", "#7ac47e"];
|
||||
const RAYS = [0, 45, 90, 135, 180, 225, 270, 315];
|
||||
// Deliberately uneven: a real burst has no protractor.
|
||||
const RAYS = [
|
||||
{ deg: 8, len: 22, r: 2.8, cls: "" },
|
||||
{ deg: 52, len: 17, r: 2.2, cls: "late" },
|
||||
{ deg: 88, len: 24, r: 3, cls: "" },
|
||||
{ deg: 141, len: 16, r: 2, cls: "later" },
|
||||
{ deg: 176, len: 21, r: 2.6, cls: "late" },
|
||||
{ deg: 224, len: 18, r: 2.3, cls: "" },
|
||||
{ deg: 267, len: 23, r: 2.8, cls: "later" },
|
||||
{ deg: 309, len: 15, r: 2, cls: "late" },
|
||||
];
|
||||
</script>
|
||||
|
||||
<g class="fireworks">
|
||||
{#each RAYS as deg, i (deg)}
|
||||
{@const dx = Math.cos((deg * Math.PI) / 180)}
|
||||
{@const dy = Math.sin((deg * Math.PI) / 180)}
|
||||
{#each RAYS as ray, i (ray.deg)}
|
||||
{@const dx = Math.cos((ray.deg * Math.PI) / 180)}
|
||||
{@const dy = Math.sin((ray.deg * Math.PI) / 180)}
|
||||
<line
|
||||
x1={c.x + 4 * dx} y1={c.y + 4 * dy}
|
||||
x2={c.x + 20 * dx} y2={c.y + 20 * dy}
|
||||
x2={c.x + ray.len * dx} y2={c.y + ray.len * dy}
|
||||
stroke={COLORS[i % 4]}
|
||||
class="trail"
|
||||
class={`trail ${ray.cls}`}
|
||||
style={`transform-origin: ${c.x}px ${c.y}px`}
|
||||
/>
|
||||
<circle
|
||||
cx={c.x + 21 * dx} cy={c.y + 21 * dy} r="2.6"
|
||||
cx={c.x + (ray.len + 1) * dx} cy={c.y + (ray.len + 1) * dy} r={ray.r}
|
||||
fill={COLORS[i % 4]}
|
||||
class="spark"
|
||||
class={`spark ${ray.cls}`}
|
||||
style={`transform-origin: ${c.x}px ${c.y}px`}
|
||||
/>
|
||||
{/each}
|
||||
@@ -36,6 +46,8 @@
|
||||
animation: trail-out 0.9s ease-out forwards;
|
||||
}
|
||||
.spark { animation: spark-out 1.05s ease-out forwards; }
|
||||
.trail.late, .spark.late { animation-delay: 0.07s; }
|
||||
.trail.later, .spark.later { animation-delay: 0.14s; }
|
||||
.heart { fill: #fffdf0; animation: heart-pop 0.4s ease-out forwards; }
|
||||
@keyframes trail-out {
|
||||
0% { opacity: 0; transform: scale(0.15); }
|
||||
|
||||
Reference in New Issue
Block a user