fix heatmap in stats for bright theme
This commit is contained in:
@@ -6,12 +6,20 @@
|
||||
let all: ActivitySummary[] = [];
|
||||
let sport: Sport | 'all' = 'all';
|
||||
let loading = true;
|
||||
let theme = 'dark';
|
||||
|
||||
onMount(async () => {
|
||||
const res = await fetch(`${import.meta.env.BASE_URL}data/index.json`);
|
||||
const index: BASIndex = await res.json();
|
||||
all = index.activities.filter(a => a.privacy !== 'private' && a.distance_m);
|
||||
loading = false;
|
||||
|
||||
theme = document.documentElement.getAttribute('data-theme') ?? 'dark';
|
||||
const obs = new MutationObserver(() => {
|
||||
theme = document.documentElement.getAttribute('data-theme') ?? 'dark';
|
||||
});
|
||||
obs.observe(document.documentElement, { attributes: true, attributeFilter: ['data-theme'] });
|
||||
return () => obs.disconnect();
|
||||
});
|
||||
|
||||
$: activities = sport === 'all' ? all : all.filter(a => a.sport === sport);
|
||||
@@ -143,20 +151,29 @@
|
||||
];
|
||||
}
|
||||
|
||||
// Lerp from zinc-800 bg (#27272a = 39,39,42) toward target color
|
||||
function applyIntensity(hex: string, intensity: number): string {
|
||||
// Base cell color: zinc-800 dark (#27272a=39,39,42) or zinc-200 light (#e4e4e7=228,228,231)
|
||||
$: emptyColor = theme === 'light' ? '#e4e4e7' : '#27272a';
|
||||
$: baseRgb = theme === 'light'
|
||||
? [228, 228, 231] as [number, number, number]
|
||||
: [39, 39, 42] as [number, number, number];
|
||||
|
||||
// Lerp from base bg color toward target sport color
|
||||
function applyIntensity(hex: string, intensity: number, base: [number, number, number]): string {
|
||||
const [tr, tg, tb] = hexToRgb(hex);
|
||||
return `rgb(${Math.round(39 + (tr - 39) * intensity)},${Math.round(39 + (tg - 39) * intensity)},${Math.round(42 + (tb - 42) * intensity)})`;
|
||||
const [br, bg, bb] = base;
|
||||
return `rgb(${Math.round(br + (tr - br) * intensity)},${Math.round(bg + (tg - bg) * intensity)},${Math.round(bb + (tb - bb) * intensity)})`;
|
||||
}
|
||||
|
||||
// Precompute date→color as a reactive Map so Svelte tracks it directly in
|
||||
// the template. (Calling a plain function with a static string arg won't
|
||||
// re-trigger when byDate/maxDailyKm change — the Map reference does.)
|
||||
$: cellColors = (() => {
|
||||
const base = baseRgb;
|
||||
const empty = emptyColor;
|
||||
const m = new Map<string, string>();
|
||||
for (const [date, sportMap] of byDateBySport) {
|
||||
const total = byDate.get(date) ?? 0;
|
||||
if (total === 0) { m.set(date, '#27272a'); continue; }
|
||||
if (total === 0) { m.set(date, empty); continue; }
|
||||
const intensity = 0.12 + pctRank(total, sortedDaily) * 0.88;
|
||||
let tr = 0, tg = 0, tb = 0;
|
||||
for (const [sp, dist] of sportMap) {
|
||||
@@ -165,15 +182,15 @@
|
||||
tr += cr * w; tg += cg * w; tb += cb * w;
|
||||
}
|
||||
const blended = `#${Math.round(tr).toString(16).padStart(2,'0')}${Math.round(tg).toString(16).padStart(2,'0')}${Math.round(tb).toString(16).padStart(2,'0')}`;
|
||||
m.set(date, applyIntensity(blended, intensity));
|
||||
m.set(date, applyIntensity(blended, intensity, base));
|
||||
}
|
||||
return m;
|
||||
})();
|
||||
|
||||
// Legend: 6 swatches from dark to full sport color (or neutral for 'all')
|
||||
$: legendColor = sport !== 'all' ? sportColor(sport) : '#00c8ff';
|
||||
// Legend: 6 swatches from base bg to full sport color (or neutral for 'all')
|
||||
$: legendColor = sport !== 'all' ? sportColor(sport) : (theme === 'light' ? '#0284c7' : '#00c8ff');
|
||||
$: legendSwatches = [0, 0.18, 0.38, 0.58, 0.78, 1.0].map(t =>
|
||||
t === 0 ? '#27272a' : applyIntensity(legendColor, t)
|
||||
t === 0 ? emptyColor : applyIntensity(legendColor, t, baseRgb)
|
||||
);
|
||||
|
||||
// Sport chips present in filtered data (for 'all' color key)
|
||||
@@ -301,12 +318,12 @@
|
||||
</div>
|
||||
{#each week as date}
|
||||
<div
|
||||
class="w-[10px] h-[10px] rounded-[2px] {date && activitiesByDate.has(date) ? 'cursor-pointer' : ''} {date && date === pinnedDate ? 'ring-1 ring-white ring-offset-[1px] ring-offset-zinc-950' : ''}"
|
||||
style="background:{cellColors.get(date) ?? '#27272a'}"
|
||||
class="w-[10px] h-[10px] rounded-[2px] {date && activitiesByDate.has(date) ? 'cursor-pointer' : ''} {date && date === pinnedDate ? 'ring-1 ring-white ring-offset-[1px]' : ''}"
|
||||
style="background:{cellColors.get(date) ?? emptyColor}; --tw-ring-offset-color: var(--bg-base)"
|
||||
on:mouseenter={e => onCellEnter(date, e)}
|
||||
on:mouseleave={onCellLeave}
|
||||
on:click={e => onCellClick(date, e)}
|
||||
/>
|
||||
></div>
|
||||
{/each}
|
||||
</div>
|
||||
{/each}
|
||||
|
||||
Reference in New Issue
Block a user