From 1d6da7da98af94ea67b77875382e26f193672e89 Mon Sep 17 00:00:00 2001 From: Ewan Croft Date: Thu, 13 Aug 2026 15:38:49 +0100 Subject: [PATCH] feat(tourmaline): add animated bar-chart race for top artists MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Precomputes one frame per month up front (running cumulative counts, snapshotted to the top 15 artists), then drives a horizontal Chart.js bar chart through the frames on a setInterval, relying on Chart.js's built-in animation to tween between frames — the standard bar-chart- race technique, no extra library. Playback (play/pause, scrubber, 0.5x/1x/2x speed) is driven by a single $effect keyed on `playing`/`speed`: the effect's cleanup clears the interval on every re-run, so pausing, changing speed, or unmounting can never leak a timer (same discipline as StoryRecap.svelte's resetAutoAdvance). Playback stops (without looping) at the last frame and the play button re-enables once the user scrubs back. Wired into the catalogue tab above the existing Top Artists list. --- .../src/routes/profile/[did]/+page.svelte | 6 + .../src/routes/profile/[did]/RaceChart.svelte | 227 ++++++++++++++++++ 2 files changed, 233 insertions(+) create mode 100644 packages/tourmaline/src/routes/profile/[did]/RaceChart.svelte diff --git a/packages/tourmaline/src/routes/profile/[did]/+page.svelte b/packages/tourmaline/src/routes/profile/[did]/+page.svelte index c3e6515..bdb5660 100644 --- a/packages/tourmaline/src/routes/profile/[did]/+page.svelte +++ b/packages/tourmaline/src/routes/profile/[did]/+page.svelte @@ -40,6 +40,7 @@ import CatalogueTab from './CatalogueTab.svelte'; import PunchcardHeatmap from './PunchcardHeatmap.svelte'; import EddingtonChart from './EddingtonChart.svelte'; + import RaceChart from './RaceChart.svelte'; import Recommendations from './Recommendations.svelte'; import TrackPreview from '$lib/components/TrackPreview.svelte'; import ListeningContext from './ListeningContext.svelte'; @@ -488,6 +489,11 @@ {:else if activeTab === 'catalogue'} + +
+ +
+
diff --git a/packages/tourmaline/src/routes/profile/[did]/RaceChart.svelte b/packages/tourmaline/src/routes/profile/[did]/RaceChart.svelte new file mode 100644 index 0000000..cfb53ce --- /dev/null +++ b/packages/tourmaline/src/routes/profile/[did]/RaceChart.svelte @@ -0,0 +1,227 @@ + + +{#if frames.length > 0} +
+
+

+ + Top Artists Race +

+ + {formatMonth(currentFrame?.month ?? '')} + +
+ +
+ +
+ +
+
+ + + + + + {frameIndex + 1}/{frames.length} + +
+ +
+ Speed + {#each SPEEDS as s (s)} + + {/each} +
+
+
+{/if} -- 2.51.2