This commit is contained in:
Vincent van der Wal
2026-07-19 16:13:51 +02:00
parent e031716ce6
commit baa4840b38
26 changed files with 1077 additions and 702 deletions
+31 -1
View File
@@ -4,7 +4,7 @@
Renders line and bar series over a shared hourly time axis on a
devicePixelRatio-aware canvas. Supports daylight background bands,
timezone-aware axis labels with emphasized day boundaries, a DOM tooltip
with crosshair, wheel/pinch zoom, drag panning, and cross-chart
with crosshair, Ctrl+wheel / pinch zoom, drag panning, and cross-chart
synchronization via the `group` prop.
Usage:
@@ -161,6 +161,16 @@
let themeVersion = $state(0);
const legendHidden = new SvelteSet<string>();
// Briefly shown when the user scrolls over the chart without holding Ctrl
let zoomHintVisible = $state(false);
let zoomHintTimeout: ReturnType<typeof setTimeout> | undefined;
function showZoomHint(): void {
zoomHintVisible = true;
clearTimeout(zoomHintTimeout);
zoomHintTimeout = setTimeout(() => (zoomHintVisible = false), 1200);
}
// Zoom range and crosshair: either group-shared or local to this chart.
// The group is acquired once at component init (the prop is treated as fixed).
const groupName = untrack(() => group);
@@ -170,6 +180,7 @@
onDestroy(() => {
if (groupName) releaseGroup(groupName);
clearTimeout(zoomHintTimeout);
});
// ─── Derived: view window & scales ──────────────────────────────────────────
@@ -737,6 +748,12 @@
};
const onWheel = (e: WheelEvent): void => {
// Zoom only while Ctrl (or ⌘) is held — a plain scroll should keep
// scrolling the page. Trackpad pinch also arrives as ctrlKey wheel.
if (!e.ctrlKey && !e.metaKey) {
showZoomHint();
return;
}
e.preventDefault();
const t = pixToTime(localX(e));
zoomAt(t, e.deltaY < 0 ? 1 / 1.3 : 1.3);
@@ -803,6 +820,19 @@
style:touch-action="pan-y"
></canvas>
{#if zoomHintVisible}
<div
class="pointer-events-none absolute inset-0 z-30 flex items-center justify-center rounded-md bg-black/25 transition-opacity"
>
<span
class="rounded-lg bg-popover px-4 py-2 text-sm font-medium text-popover-foreground shadow-lg"
>
Hold <kbd class="rounded border border-border bg-muted px-1.5 py-0.5 text-xs">Ctrl</kbd>
and scroll to zoom
</span>
</div>
{/if}
{#if tooltipVisible}
<div
class="pointer-events-none absolute z-20 rounded-md border border-border bg-popover px-3 py-2 text-xs whitespace-nowrap text-popover-foreground shadow-md"