From d5e2f288d6cf4acebd2a7c096d217ae490d7f47a Mon Sep 17 00:00:00 2001 From: Cory Virok Date: Tue, 4 Mar 2025 11:53:37 -0800 Subject: [PATCH 1/3] added a BrushContext example This shows how to sync a BruchContext's xDomain with an external chart. Note: There is a bug related to zooming on the chart. It should not be able to zoom but if you double click on the chart it will zoom in the entire chart. --- .../layerchart/src/routes/_NavMenu.svelte | 1 + .../examples/SyncBrushContext/+page.svelte | 130 ++++++++++++++++++ .../docs/examples/SyncBrushContext/+page.ts | 15 ++ 3 files changed, 146 insertions(+) create mode 100644 packages/layerchart/src/routes/docs/examples/SyncBrushContext/+page.svelte create mode 100644 packages/layerchart/src/routes/docs/examples/SyncBrushContext/+page.ts diff --git a/packages/layerchart/src/routes/_NavMenu.svelte b/packages/layerchart/src/routes/_NavMenu.svelte index 67bc6dd62..7217667b0 100644 --- a/packages/layerchart/src/routes/_NavMenu.svelte +++ b/packages/layerchart/src/routes/_NavMenu.svelte @@ -28,6 +28,7 @@ 'Scatter', 'Sparkbar', 'Sparkline', + 'SyncBrushContext', 'Threshold', ], Hierarchy: ['Pack', 'Partition', 'Sunburst', 'Tree', 'Treemap'], diff --git a/packages/layerchart/src/routes/docs/examples/SyncBrushContext/+page.svelte b/packages/layerchart/src/routes/docs/examples/SyncBrushContext/+page.svelte new file mode 100644 index 000000000..ec2403142 --- /dev/null +++ b/packages/layerchart/src/routes/docs/examples/SyncBrushContext/+page.svelte @@ -0,0 +1,130 @@ + + +

Sync BrushContext

+ + + +
+ { + // Invert deltaX for more natural horizontal scrolling + translateXDomain(-deltaX) + return { x: 0, y: 0} + } + }} + > + + + + + + + + + + +
+ +
+ (xDomain = e.xDomain), + onreset: () => (xDomain = undefined) + }} + > + + + + +
+
\ No newline at end of file diff --git a/packages/layerchart/src/routes/docs/examples/SyncBrushContext/+page.ts b/packages/layerchart/src/routes/docs/examples/SyncBrushContext/+page.ts new file mode 100644 index 000000000..dbfbab08d --- /dev/null +++ b/packages/layerchart/src/routes/docs/examples/SyncBrushContext/+page.ts @@ -0,0 +1,15 @@ +import { parse } from '@layerstack/utils'; + +import pageSource from './+page.svelte?raw'; +import type { AppleStockData } from '$static/data/examples/date/apple-stock.js'; + +export async function load({fetch}) { + return { + appleStock: await fetch('/data/examples/date/apple-stock.json').then(async (r) => + parse(await r.text()) + ), + meta: { + pageSource, + }, + }; +} From e0f9b103b6c1c18efdd23d4b4fea1aa9257e8596 Mon Sep 17 00:00:00 2001 From: Cory Virok Date: Tue, 4 Mar 2025 11:55:56 -0800 Subject: [PATCH 2/3] fix formatting for latest example --- .../examples/SyncBrushContext/+page.svelte | 188 +++++++++--------- 1 file changed, 93 insertions(+), 95 deletions(-) diff --git a/packages/layerchart/src/routes/docs/examples/SyncBrushContext/+page.svelte b/packages/layerchart/src/routes/docs/examples/SyncBrushContext/+page.svelte index ec2403142..56fe5e050 100644 --- a/packages/layerchart/src/routes/docs/examples/SyncBrushContext/+page.svelte +++ b/packages/layerchart/src/routes/docs/examples/SyncBrushContext/+page.svelte @@ -4,127 +4,125 @@ import { geoAlbersUsa, geoAlbers, geoMercator, geoPath as d3geoPath } from 'd3-geo'; import { feature } from 'topojson-client'; - import { Area, Axis, Canvas, Chart, ChartClipPath, GeoPath, LinearGradient, Svg, Tooltip, geoFitObjectTransform } from 'layerchart'; + import { + Area, + Axis, + Canvas, + Chart, + ChartClipPath, + GeoPath, + LinearGradient, + Svg, + Tooltip, + geoFitObjectTransform, + } from 'layerchart'; import TransformControls from '$lib/components/TransformControls.svelte'; import { SelectField } from 'svelte-ux'; import Preview from '$lib/docs/Preview.svelte'; import type { GeometryObjectA } from 'topojson-specification'; - import { mdiNumeric0BoxMultiple } from '@mdi/js'; - import type { DomainType } from 'layerchart/utils/scales.js'; - import { extent } from 'd3-array'; - import { scaleTime } from 'd3-scale'; - + import { mdiNumeric0BoxMultiple } from '@mdi/js'; + import type { DomainType } from 'layerchart/utils/scales.js'; + import { extent } from 'd3-array'; + import { scaleTime } from 'd3-scale'; export let data; - const xScale = scaleTime() + const xScale = scaleTime(); - let xDomain: DomainType | undefined = [null, null] - let yDomain: DomainType = [0, null] + let xDomain: DomainType | undefined = [null, null]; + let yDomain: DomainType = [0, null]; - $: xRange = buildXRange(data.appleStock) - $: yDomain = extent(data.appleStock, (d) => d.value) + $: xRange = buildXRange(data.appleStock); + $: yDomain = extent(data.appleStock, (d) => d.value); - function buildXRange(data: {date: Date; value: number}[]) { - const xExtent = extent(data, (d) => d.date) + function buildXRange(data: { date: Date; value: number }[]) { + const xExtent = extent(data, (d) => d.date); if (xExtent[0] instanceof Date && xExtent[1] instanceof Date) { - return [xScale(xExtent[0]), xScale(xExtent[1])] + return [xScale(xExtent[0]), xScale(xExtent[1])]; } - return [null, null] + return [null, null]; } - + function translateXDomain(deltaX: number) { if (deltaX && xDomain?.[0] && xRange[0] !== null && xRange[1] !== null) { - const curStartX = xScale(xDomain[0] as Date) - const curEndX = xScale(xDomain[1] as Date) - const origDelta = curEndX - curStartX + const curStartX = xScale(xDomain[0] as Date); + const curEndX = xScale(xDomain[1] as Date); + const origDelta = curEndX - curStartX; - let newStartX: number - let newEndX: number + let newStartX: number; + let newEndX: number; if (deltaX > 0) { - newEndX = Math.min(curEndX + deltaX, xRange[1]) - newStartX = newEndX - origDelta + newEndX = Math.min(curEndX + deltaX, xRange[1]); + newStartX = newEndX - origDelta; } else { - newStartX = Math.max(curStartX + deltaX, xRange[0]) - newEndX = newStartX + origDelta + newStartX = Math.max(curStartX + deltaX, xRange[0]); + newEndX = newStartX + origDelta; } - const newStartDate = xScale.invert(newStartX) - const newEndDate = xScale.invert(newEndX) + const newStartDate = xScale.invert(newStartX); + const newEndDate = xScale.invert(newEndX); - xDomain = [newStartDate, newEndDate] + xDomain = [newStartDate, newEndDate]; } } -

Sync BrushContext

- - -
- { - // Invert deltaX for more natural horizontal scrolling - translateXDomain(-deltaX) - return { x: 0, y: 0} - } - }} - > - - - - - - - - - - -
- -
- (xDomain = e.xDomain), - onreset: () => (xDomain = undefined) - }} - > - - - - -
-
\ No newline at end of file + +
+ { + // Invert deltaX for more natural horizontal scrolling + translateXDomain(-deltaX); + return { x: 0, y: 0 }; + }, + }} + > + + + + + + + + + + +
+ +
+ (xDomain = e.xDomain), + onreset: () => (xDomain = undefined), + }} + > + + + + +
+
From 76e6ecbf91b08caab19105e13f09f8cada9a19af Mon Sep 17 00:00:00 2001 From: Cory Virok Date: Tue, 4 Mar 2025 11:58:21 -0800 Subject: [PATCH 3/3] actually fix formatting (using top-level format target) --- .../src/routes/docs/examples/SyncBrushContext/+page.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/layerchart/src/routes/docs/examples/SyncBrushContext/+page.ts b/packages/layerchart/src/routes/docs/examples/SyncBrushContext/+page.ts index dbfbab08d..f34b8d0af 100644 --- a/packages/layerchart/src/routes/docs/examples/SyncBrushContext/+page.ts +++ b/packages/layerchart/src/routes/docs/examples/SyncBrushContext/+page.ts @@ -3,7 +3,7 @@ import { parse } from '@layerstack/utils'; import pageSource from './+page.svelte?raw'; import type { AppleStockData } from '$static/data/examples/date/apple-stock.js'; -export async function load({fetch}) { +export async function load({ fetch }) { return { appleStock: await fetch('/data/examples/date/apple-stock.json').then(async (r) => parse(await r.text())