layerchart 0.3.6 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/components/Arc.svelte +2 -2
- package/components/Arc.svelte.d.ts +2 -0
- package/components/Area.svelte +1 -1
- package/components/AreaStack.svelte +1 -1
- package/components/AxisX.svelte +2 -2
- package/components/AxisY.svelte +2 -2
- package/components/Bars.svelte +1 -1
- package/components/Baseline.svelte +2 -2
- package/components/Bounds.svelte +24 -0
- package/components/Bounds.svelte.d.ts +48 -0
- package/components/Chart.svelte +2 -2
- package/components/ChartClipPath.svelte +14 -0
- package/components/ChartClipPath.svelte.d.ts +18 -0
- package/components/Circle.svelte +1 -1
- package/components/CircleClipPath.svelte +1 -1
- package/components/ClipPath.svelte +1 -1
- package/components/ConnectedPoints.svelte +1 -1
- package/components/Group.svelte +1 -1
- package/components/HighlightLine.svelte +1 -1
- package/components/HighlightRect.svelte +1 -1
- package/components/Labels.svelte +1 -1
- package/components/Line.svelte +1 -1
- package/components/LinearGradient.svelte +1 -1
- package/components/Link.svelte +7 -2
- package/components/Link.svelte.d.ts +4 -0
- package/components/Partition.svelte +27 -0
- package/components/Partition.svelte.d.ts +27 -0
- package/components/Path.svelte +2 -2
- package/components/Pattern.svelte +1 -1
- package/components/Pie.svelte +1 -1
- package/components/Points.svelte +8 -6
- package/components/Points.svelte.d.ts +5 -1
- package/components/Rect.svelte +1 -1
- package/components/RectClipPath.svelte +1 -1
- package/components/Sankey.svelte +1 -1
- package/components/Text.svelte +1 -1
- package/components/Threshold.svelte +1 -1
- package/components/Tooltip.svelte +1 -1
- package/components/Tree.svelte +30 -0
- package/components/Tree.svelte.d.ts +32 -0
- package/components/Treemap.svelte +10 -41
- package/components/Treemap.svelte.d.ts +0 -6
- package/components/Zoom.svelte +108 -0
- package/components/Zoom.svelte.d.ts +25 -0
- package/components/index.d.ts +2 -0
- package/components/index.js +2 -0
- package/docs/Preview.svelte +1 -1
- package/package.json +25 -21
- package/utils/genData.d.ts +19 -0
- package/utils/genData.js +16 -0
- package/utils/math.d.ts +4 -0
- package/utils/math.js +6 -0
- package/utils/scales.d.ts +17 -0
- package/utils/scales.js +46 -0
package/components/Arc.svelte
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<script
|
|
1
|
+
<script>/*
|
|
2
2
|
TODO:
|
|
3
3
|
- [ ] Allow spring/tweened to be reactive (but ignore value)
|
|
4
4
|
*/
|
|
@@ -110,6 +110,6 @@ $: yOffset = -Math.cos(angle) * offset;
|
|
|
110
110
|
<path d={trackArc()} class="track" bind:this={trackArcEl} {...track} />
|
|
111
111
|
{/if}
|
|
112
112
|
|
|
113
|
-
<path d={arc()} transform="translate({xOffset}, {yOffset})" {...$$restProps} />
|
|
113
|
+
<path d={arc()} transform="translate({xOffset}, {yOffset})" {...$$restProps} on:click />
|
|
114
114
|
|
|
115
115
|
<slot value={$tweened_value} centroid={trackArcCentroid} {boundingBox} />
|
package/components/Area.svelte
CHANGED
package/components/AxisX.svelte
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<script
|
|
1
|
+
<script>import { getContext } from 'svelte';
|
|
2
2
|
import { format } from 'svelte-ux/utils/format';
|
|
3
3
|
import Text from './Text.svelte';
|
|
4
4
|
import { isScaleBand } from '../utils/scales';
|
|
@@ -39,7 +39,7 @@ $: tickVals = Array.isArray(ticks)
|
|
|
39
39
|
{/each}
|
|
40
40
|
</g>
|
|
41
41
|
|
|
42
|
-
<style
|
|
42
|
+
<style>
|
|
43
43
|
.tick {
|
|
44
44
|
font-size: 0.725em;
|
|
45
45
|
font-weight: 200;
|
package/components/AxisY.svelte
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<script
|
|
1
|
+
<script>import { getContext } from 'svelte';
|
|
2
2
|
import { format } from 'svelte-ux/utils/format';
|
|
3
3
|
import Text from './Text.svelte';
|
|
4
4
|
import { isScaleBand } from '../utils/scales';
|
|
@@ -53,7 +53,7 @@ $: tickVals = Array.isArray(ticks)
|
|
|
53
53
|
{/each}
|
|
54
54
|
</g>
|
|
55
55
|
|
|
56
|
-
<style
|
|
56
|
+
<style>
|
|
57
57
|
.tick {
|
|
58
58
|
font-size: 0.725em;
|
|
59
59
|
font-weight: 200;
|
package/components/Bars.svelte
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<script
|
|
1
|
+
<script>import { getContext } from 'svelte';
|
|
2
2
|
const { xRange, yScale, yRange } = getContext('LayerCake');
|
|
3
3
|
export let x = false;
|
|
4
4
|
export let y = false;
|
|
@@ -14,7 +14,7 @@ export let y = false;
|
|
|
14
14
|
{/if}
|
|
15
15
|
</g>
|
|
16
16
|
|
|
17
|
-
<style
|
|
17
|
+
<style>
|
|
18
18
|
.baseline {
|
|
19
19
|
stroke: #777;
|
|
20
20
|
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
<script>import { getContext } from 'svelte';
|
|
2
|
+
import { cubicOut } from 'svelte/easing';
|
|
3
|
+
import { scaleLinear } from 'd3-scale';
|
|
4
|
+
import { tweenedScale } from '../utils/scales';
|
|
5
|
+
const { width, height } = getContext('LayerCake');
|
|
6
|
+
export let domain;
|
|
7
|
+
export let range;
|
|
8
|
+
const tweenedOptions = { easing: cubicOut, duration: 800 };
|
|
9
|
+
function getExtents(extents, axis, fallback) {
|
|
10
|
+
const resolvedExtents = typeof extents === 'function' ? extents({ width: $width, height: $height }) : extents;
|
|
11
|
+
return [
|
|
12
|
+
resolvedExtents?.[axis + '0'] ?? 0,
|
|
13
|
+
resolvedExtents?.[axis + '1'] ?? fallback // x1 or y1, fallback as $width or $height
|
|
14
|
+
];
|
|
15
|
+
}
|
|
16
|
+
const xScale = tweenedScale(scaleLinear, tweenedOptions);
|
|
17
|
+
$: xScale.domain(getExtents(domain, 'x', $width));
|
|
18
|
+
$: xScale.range(getExtents(range, 'x', $width));
|
|
19
|
+
const yScale = tweenedScale(scaleLinear, tweenedOptions);
|
|
20
|
+
$: yScale.domain(getExtents(domain, 'y', $height));
|
|
21
|
+
$: yScale.range(getExtents(range, 'y', $height));
|
|
22
|
+
</script>
|
|
23
|
+
|
|
24
|
+
<slot xScale={$xScale} yScale={$yScale} />
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { SvelteComponentTyped } from "svelte";
|
|
2
|
+
declare const __propDef: {
|
|
3
|
+
props: {
|
|
4
|
+
domain: {
|
|
5
|
+
x0: number;
|
|
6
|
+
y0: number;
|
|
7
|
+
x1: number;
|
|
8
|
+
y1: number;
|
|
9
|
+
} | ((dimensions: {
|
|
10
|
+
width: number;
|
|
11
|
+
height: number;
|
|
12
|
+
}) => {
|
|
13
|
+
x0: number;
|
|
14
|
+
y0: number;
|
|
15
|
+
x1: number;
|
|
16
|
+
y1: number;
|
|
17
|
+
});
|
|
18
|
+
range: {
|
|
19
|
+
x0: number;
|
|
20
|
+
y0: number;
|
|
21
|
+
x1: number;
|
|
22
|
+
y1: number;
|
|
23
|
+
} | ((dimensions: {
|
|
24
|
+
width: number;
|
|
25
|
+
height: number;
|
|
26
|
+
}) => {
|
|
27
|
+
x0: number;
|
|
28
|
+
y0: number;
|
|
29
|
+
x1: number;
|
|
30
|
+
y1: number;
|
|
31
|
+
});
|
|
32
|
+
};
|
|
33
|
+
events: {
|
|
34
|
+
[evt: string]: CustomEvent<any>;
|
|
35
|
+
};
|
|
36
|
+
slots: {
|
|
37
|
+
default: {
|
|
38
|
+
xScale: any;
|
|
39
|
+
yScale: any;
|
|
40
|
+
};
|
|
41
|
+
};
|
|
42
|
+
};
|
|
43
|
+
export declare type BoundsProps = typeof __propDef.props;
|
|
44
|
+
export declare type BoundsEvents = typeof __propDef.events;
|
|
45
|
+
export declare type BoundsSlots = typeof __propDef.slots;
|
|
46
|
+
export default class Bounds extends SvelteComponentTyped<BoundsProps, BoundsEvents, BoundsSlots> {
|
|
47
|
+
}
|
|
48
|
+
export {};
|
package/components/Chart.svelte
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
<script context="module"
|
|
1
|
+
<script context="module">import { LayerCake, Svg, Html } from 'layercake';
|
|
2
2
|
export { Svg, Html };
|
|
3
3
|
</script>
|
|
4
4
|
|
|
5
|
-
<script
|
|
5
|
+
<script>import { max, min } from 'd3-array';
|
|
6
6
|
import { get } from 'lodash-es';
|
|
7
7
|
/**
|
|
8
8
|
* Resolve a value from data based on the accessor type
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
<script>import { getContext } from 'svelte';
|
|
2
|
+
import RectClipPath from './RectClipPath.svelte';
|
|
3
|
+
const { width, height, padding } = getContext('LayerCake');
|
|
4
|
+
</script>
|
|
5
|
+
|
|
6
|
+
<RectClipPath
|
|
7
|
+
x={-$padding.left}
|
|
8
|
+
y={-$padding.top}
|
|
9
|
+
width={$width + $padding.left + $padding.right}
|
|
10
|
+
height={$height + $padding.top + $padding.bottom}
|
|
11
|
+
{...$$restProps}
|
|
12
|
+
>
|
|
13
|
+
<slot />
|
|
14
|
+
</RectClipPath>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { SvelteComponentTyped } from "svelte";
|
|
2
|
+
declare const __propDef: {
|
|
3
|
+
props: {
|
|
4
|
+
[x: string]: any;
|
|
5
|
+
};
|
|
6
|
+
events: {
|
|
7
|
+
[evt: string]: CustomEvent<any>;
|
|
8
|
+
};
|
|
9
|
+
slots: {
|
|
10
|
+
default: {};
|
|
11
|
+
};
|
|
12
|
+
};
|
|
13
|
+
export declare type ChartClipPathProps = typeof __propDef.props;
|
|
14
|
+
export declare type ChartClipPathEvents = typeof __propDef.events;
|
|
15
|
+
export declare type ChartClipPathSlots = typeof __propDef.slots;
|
|
16
|
+
export default class ChartClipPath extends SvelteComponentTyped<ChartClipPathProps, ChartClipPathEvents, ChartClipPathSlots> {
|
|
17
|
+
}
|
|
18
|
+
export {};
|
package/components/Circle.svelte
CHANGED
package/components/Group.svelte
CHANGED
package/components/Labels.svelte
CHANGED
package/components/Line.svelte
CHANGED
package/components/Link.svelte
CHANGED
|
@@ -1,21 +1,26 @@
|
|
|
1
|
-
<script
|
|
1
|
+
<script>import { link as d3Link, curveBumpX, curveBumpY } from 'd3-shape';
|
|
2
2
|
import { interpolatePath } from 'd3-interpolate-path';
|
|
3
3
|
import { createMotionStore } from '../stores/motionStore';
|
|
4
4
|
// Properties to override what is used from context
|
|
5
5
|
export let data = undefined; // TODO: Update Type
|
|
6
|
+
export let orientation = 'horizontal';
|
|
6
7
|
/**
|
|
7
8
|
* Update source and target accessors to be compatibke with d3-sankey. see: https://github.com/d3/d3-sankey#sankeyLinkHorizontal
|
|
8
9
|
*/
|
|
9
10
|
export let sankey = false;
|
|
10
11
|
export let source = sankey ? (d) => [d.source.x1, d.y0] : (d) => d.source;
|
|
11
12
|
export let target = sankey ? (d) => [d.target.x0, d.y1] : (d) => d.target;
|
|
13
|
+
export let x = sankey ? (d) => d[0] : (d) => (orientation === 'horizontal' ? d.y : d.x);
|
|
14
|
+
export let y = sankey ? (d) => d[1] : (d) => (orientation === 'horizontal' ? d.x : d.y);
|
|
15
|
+
export let curve = orientation === 'horizontal' ? curveBumpX : curveBumpY;
|
|
12
16
|
export let tweened = undefined;
|
|
13
17
|
export let color = 'black';
|
|
14
18
|
export let width = undefined;
|
|
15
19
|
$: tweenedOptions = tweened ? { interpolate: interpolatePath, ...tweened } : false;
|
|
16
20
|
$: tweened_d = createMotionStore('', { tweened: tweenedOptions });
|
|
17
21
|
$: {
|
|
18
|
-
|
|
22
|
+
orientation; // subscribe to orientation changes to link is update
|
|
23
|
+
const link = d3Link(curve).source(source).target(target).x(x).y(y);
|
|
19
24
|
const d = link(data);
|
|
20
25
|
tweened_d.set(d);
|
|
21
26
|
}
|
|
@@ -4,9 +4,13 @@ declare const __propDef: {
|
|
|
4
4
|
props: {
|
|
5
5
|
[x: string]: any;
|
|
6
6
|
data?: any;
|
|
7
|
+
orientation?: 'vertical' | 'horizontal';
|
|
7
8
|
sankey?: boolean;
|
|
8
9
|
source?: (d: any) => any;
|
|
9
10
|
target?: (d: any) => any;
|
|
11
|
+
x?: (d: any) => any;
|
|
12
|
+
y?: (d: any) => any;
|
|
13
|
+
curve?: import("d3-shape").CurveFactory;
|
|
10
14
|
tweened?: boolean | Parameters<typeof tweenedStore>[1];
|
|
11
15
|
color?: string;
|
|
12
16
|
width?: any;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
<script>import { getContext } from 'svelte';
|
|
2
|
+
import { partition as d3Partition } from 'd3-hierarchy';
|
|
3
|
+
const { data, width, height } = getContext('LayerCake');
|
|
4
|
+
export let orientation = 'horizontal';
|
|
5
|
+
export let size = undefined;
|
|
6
|
+
/**
|
|
7
|
+
* see: https://github.com/d3/d3-hierarchy#tree_nodeSize
|
|
8
|
+
*/
|
|
9
|
+
export let padding = undefined;
|
|
10
|
+
/**
|
|
11
|
+
* see: https://github.com/d3/d3-hierarchy#tree_nodeSize
|
|
12
|
+
*/
|
|
13
|
+
export let round = undefined;
|
|
14
|
+
let partition;
|
|
15
|
+
$: {
|
|
16
|
+
partition = d3Partition().size(size ?? (orientation === 'horizontal' ? [$height, $width] : [$width, $height]));
|
|
17
|
+
if (padding) {
|
|
18
|
+
partition.padding(padding);
|
|
19
|
+
}
|
|
20
|
+
if (round) {
|
|
21
|
+
partition.round(round);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
$: partitionData = partition($data);
|
|
25
|
+
</script>
|
|
26
|
+
|
|
27
|
+
<slot nodes={partitionData.descendants()} />
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { SvelteComponentTyped } from "svelte";
|
|
2
|
+
declare const __propDef: {
|
|
3
|
+
props: {
|
|
4
|
+
orientation?: 'vertical' | 'horizontal';
|
|
5
|
+
size?: [number, number] | undefined;
|
|
6
|
+
/**
|
|
7
|
+
* see: https://github.com/d3/d3-hierarchy#tree_nodeSize
|
|
8
|
+
*/ padding?: number | undefined;
|
|
9
|
+
/**
|
|
10
|
+
* see: https://github.com/d3/d3-hierarchy#tree_nodeSize
|
|
11
|
+
*/ round?: boolean | undefined;
|
|
12
|
+
};
|
|
13
|
+
events: {
|
|
14
|
+
[evt: string]: CustomEvent<any>;
|
|
15
|
+
};
|
|
16
|
+
slots: {
|
|
17
|
+
default: {
|
|
18
|
+
nodes: import("d3-hierarchy").HierarchyRectangularNode<unknown>[];
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
};
|
|
22
|
+
export declare type PartitionProps = typeof __propDef.props;
|
|
23
|
+
export declare type PartitionEvents = typeof __propDef.events;
|
|
24
|
+
export declare type PartitionSlots = typeof __propDef.slots;
|
|
25
|
+
export default class Partition extends SvelteComponentTyped<PartitionProps, PartitionEvents, PartitionSlots> {
|
|
26
|
+
}
|
|
27
|
+
export {};
|
package/components/Path.svelte
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<script
|
|
1
|
+
<script>/*
|
|
2
2
|
TODO:
|
|
3
3
|
- [ ] Show path progressively show / animated in on load. Also fix sliding in from left side (at last in from bottom)
|
|
4
4
|
*/
|
|
@@ -35,7 +35,7 @@ $: {
|
|
|
35
35
|
|
|
36
36
|
<path class="path-line" d={$tweened_d} stroke={color} stroke-width={width} {...$$restProps} />
|
|
37
37
|
|
|
38
|
-
<style
|
|
38
|
+
<style>
|
|
39
39
|
.path-line {
|
|
40
40
|
fill: none;
|
|
41
41
|
stroke-linejoin: round;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<script
|
|
1
|
+
<script>// https://developer.mozilla.org/en-US/docs/Web/SVG/Element/pattern
|
|
2
2
|
// https://airbnb.io/visx/patterns
|
|
3
3
|
// https://github.com/airbnb/visx/tree/master/packages/visx-pattern/src/patterns
|
|
4
4
|
export let id;
|
package/components/Pie.svelte
CHANGED
package/components/Points.svelte
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<script
|
|
1
|
+
<script>import { getContext } from 'svelte';
|
|
2
2
|
import Circle from './Circle.svelte';
|
|
3
3
|
import { isScaleBand } from '../utils/scales';
|
|
4
4
|
const context = getContext('LayerCake');
|
|
@@ -58,8 +58,10 @@ $: points = $data.flatMap((d) => {
|
|
|
58
58
|
});
|
|
59
59
|
</script>
|
|
60
60
|
|
|
61
|
-
<
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
61
|
+
<slot {points}>
|
|
62
|
+
<g class="point-group">
|
|
63
|
+
{#each points as point}
|
|
64
|
+
<Circle cx={point.x} cy={point.y} {r} {...$$restProps} />
|
|
65
|
+
{/each}
|
|
66
|
+
</g>
|
|
67
|
+
</slot>
|
|
@@ -9,7 +9,11 @@ declare const __propDef: {
|
|
|
9
9
|
events: {
|
|
10
10
|
[evt: string]: CustomEvent<any>;
|
|
11
11
|
};
|
|
12
|
-
slots: {
|
|
12
|
+
slots: {
|
|
13
|
+
default: {
|
|
14
|
+
points: any;
|
|
15
|
+
};
|
|
16
|
+
};
|
|
13
17
|
};
|
|
14
18
|
export declare type PointsProps = typeof __propDef.props;
|
|
15
19
|
export declare type PointsEvents = typeof __propDef.events;
|
package/components/Rect.svelte
CHANGED
package/components/Sankey.svelte
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<script
|
|
1
|
+
<script>// https://github.com/d3/d3-sankey
|
|
2
2
|
import { createEventDispatcher, getContext } from 'svelte';
|
|
3
3
|
import { sankey as d3Sankey, sankeyLeft, sankeyCenter, sankeyRight, sankeyJustify } from 'd3-sankey';
|
|
4
4
|
const dispatch = createEventDispatcher();
|
package/components/Text.svelte
CHANGED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
<script>import { getContext } from 'svelte';
|
|
2
|
+
import { tree as d3Tree } from 'd3-hierarchy';
|
|
3
|
+
const { data, width, height, padding } = getContext('LayerCake');
|
|
4
|
+
/**
|
|
5
|
+
* Sets this tree layout’s node size to the specified two-element array of numbers `[width, height]`.
|
|
6
|
+
* If unset, layout size is used instead. When a node size is specified, the root node is always
|
|
7
|
+
* positioned at `⟨0, 0⟩`.
|
|
8
|
+
*
|
|
9
|
+
* see: https://github.com/d3/d3-hierarchy#tree_nodeSize
|
|
10
|
+
*/
|
|
11
|
+
export let nodeSize = undefined;
|
|
12
|
+
/**
|
|
13
|
+
* see: https://github.com/d3/d3-hierarchy#tree_separation
|
|
14
|
+
*/
|
|
15
|
+
export let separation = undefined;
|
|
16
|
+
export let orientation = 'horizontal';
|
|
17
|
+
let tree;
|
|
18
|
+
$: {
|
|
19
|
+
tree = d3Tree().size(orientation === 'horizontal' ? [$height, $width] : [$width, $height]);
|
|
20
|
+
if (nodeSize) {
|
|
21
|
+
tree.nodeSize(nodeSize);
|
|
22
|
+
}
|
|
23
|
+
if (separation) {
|
|
24
|
+
tree.separation(separation);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
$: treeData = tree($data);
|
|
28
|
+
</script>
|
|
29
|
+
|
|
30
|
+
<slot nodes={treeData.descendants()} links={treeData.links()} />
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { SvelteComponentTyped } from "svelte";
|
|
2
|
+
import { HierarchyPointNode } from 'd3-hierarchy';
|
|
3
|
+
declare const __propDef: {
|
|
4
|
+
props: {
|
|
5
|
+
/**
|
|
6
|
+
* Sets this tree layout’s node size to the specified two-element array of numbers `[width, height]`.
|
|
7
|
+
* If unset, layout size is used instead. When a node size is specified, the root node is always
|
|
8
|
+
* positioned at `⟨0, 0⟩`.
|
|
9
|
+
*
|
|
10
|
+
* see: https://github.com/d3/d3-hierarchy#tree_nodeSize
|
|
11
|
+
*/ nodeSize?: [number, number] | undefined;
|
|
12
|
+
/**
|
|
13
|
+
* see: https://github.com/d3/d3-hierarchy#tree_separation
|
|
14
|
+
*/ separation?: (a: HierarchyPointNode<any>, b: HierarchyPointNode<any>) => number;
|
|
15
|
+
orientation?: 'vertical' | 'horizontal';
|
|
16
|
+
};
|
|
17
|
+
events: {
|
|
18
|
+
[evt: string]: CustomEvent<any>;
|
|
19
|
+
};
|
|
20
|
+
slots: {
|
|
21
|
+
default: {
|
|
22
|
+
nodes: any;
|
|
23
|
+
links: any;
|
|
24
|
+
};
|
|
25
|
+
};
|
|
26
|
+
};
|
|
27
|
+
export declare type TreeProps = typeof __propDef.props;
|
|
28
|
+
export declare type TreeEvents = typeof __propDef.events;
|
|
29
|
+
export declare type TreeSlots = typeof __propDef.slots;
|
|
30
|
+
export default class Tree extends SvelteComponentTyped<TreeProps, TreeEvents, TreeSlots> {
|
|
31
|
+
}
|
|
32
|
+
export {};
|
|
@@ -1,14 +1,10 @@
|
|
|
1
|
-
<script
|
|
1
|
+
<script>/**
|
|
2
2
|
* TODO:
|
|
3
3
|
* - [ ] Improve zoomable nested (apply extent ratio? const extentRatio = ($extents.y1 - $extents.y0) / $height;
|
|
4
4
|
*/
|
|
5
5
|
import { getContext } from 'svelte';
|
|
6
|
-
import { tweened } from 'svelte/motion';
|
|
7
|
-
import { cubicOut } from 'svelte/easing';
|
|
8
6
|
import * as d3 from 'd3-hierarchy';
|
|
9
|
-
import { scaleLinear } from 'd3-scale';
|
|
10
7
|
import { group } from 'd3-array';
|
|
11
|
-
import RectClipPath from './RectClipPath.svelte';
|
|
12
8
|
import { aspectTile } from '../utils/treemap';
|
|
13
9
|
const { data, width, height } = getContext('LayerCake');
|
|
14
10
|
export let tile = d3.treemapSquarify;
|
|
@@ -61,43 +57,16 @@ $: {
|
|
|
61
57
|
}
|
|
62
58
|
}
|
|
63
59
|
$: root = treemap($data);
|
|
60
|
+
// TODO: Remove selected
|
|
64
61
|
$: selected = root; // set initial selection
|
|
65
|
-
// group nodes by depth so can be rendered lowest to highest
|
|
62
|
+
// group nodes by depth so can be rendered lowest to highest, to stack properly
|
|
66
63
|
$: nodesByDepth = group(root, (d) => d.depth);
|
|
67
|
-
const duration = 800;
|
|
68
|
-
const extents = tweened(undefined, { easing: cubicOut, duration });
|
|
69
|
-
$: $extents = selected
|
|
70
|
-
? {
|
|
71
|
-
x0: selected.x0,
|
|
72
|
-
y0: selected.y0,
|
|
73
|
-
x1: selected.x1,
|
|
74
|
-
y1: selected.y1
|
|
75
|
-
}
|
|
76
|
-
: {
|
|
77
|
-
x0: 0,
|
|
78
|
-
y0: 0,
|
|
79
|
-
x1: $width,
|
|
80
|
-
y1: $height
|
|
81
|
-
};
|
|
82
|
-
$: xScale = scaleLinear().domain([$extents.x0, $extents.x1]).rangeRound([0, $width]);
|
|
83
|
-
$: yScale = scaleLinear().domain([$extents.y0, $extents.y1]).rangeRound([0, $height]);
|
|
84
64
|
</script>
|
|
85
65
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
rect={{
|
|
94
|
-
x: xScale(node.x0),
|
|
95
|
-
y: yScale(node.y0),
|
|
96
|
-
width: xScale(node.x1) - xScale(node.x0),
|
|
97
|
-
height: yScale(node.y1) - yScale(node.y0)
|
|
98
|
-
}}
|
|
99
|
-
/>
|
|
100
|
-
{/each}
|
|
101
|
-
</g>
|
|
102
|
-
{/each}
|
|
103
|
-
</RectClipPath>
|
|
66
|
+
{#each Array.from(nodesByDepth) as [depth, nodes]}
|
|
67
|
+
<g>
|
|
68
|
+
{#each nodes as node, i (nodeKey(node, i))}
|
|
69
|
+
<slot name="node" {node} />
|
|
70
|
+
{/each}
|
|
71
|
+
</g>
|
|
72
|
+
{/each}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
<script>import { getContext } from 'svelte';
|
|
2
|
+
import { spring } from 'svelte/motion';
|
|
3
|
+
const { width, height, padding } = getContext('LayerCake');
|
|
4
|
+
let dragging = false;
|
|
5
|
+
let translate = spring({ x: 0, y: 0 });
|
|
6
|
+
let scale = spring({ x: 1, y: 1 });
|
|
7
|
+
let startPoint;
|
|
8
|
+
let startTranslate;
|
|
9
|
+
let svgEl = null;
|
|
10
|
+
export function reset() {
|
|
11
|
+
$translate = { x: 0, y: 0 };
|
|
12
|
+
$scale = { x: 1, y: 1 };
|
|
13
|
+
}
|
|
14
|
+
export function increase() {
|
|
15
|
+
$scale = {
|
|
16
|
+
x: $scale.x * 1.25,
|
|
17
|
+
y: $scale.y * 1.25
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
export function decrease() {
|
|
21
|
+
$scale = {
|
|
22
|
+
x: $scale.x * 0.8,
|
|
23
|
+
y: $scale.y * 0.8
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
export function translateCenter() {
|
|
27
|
+
$translate = {
|
|
28
|
+
x: 0,
|
|
29
|
+
y: 0
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
function handleMouseDown(e) {
|
|
33
|
+
dragging = true;
|
|
34
|
+
svgEl = e.target.ownerSVGElement;
|
|
35
|
+
startPoint = localPoint(svgEl, e);
|
|
36
|
+
startTranslate = $translate;
|
|
37
|
+
window.addEventListener('mousemove', handleMouseMove);
|
|
38
|
+
window.addEventListener('mouseup', handleMouseUp);
|
|
39
|
+
}
|
|
40
|
+
function handleMouseUp(e) {
|
|
41
|
+
dragging = false;
|
|
42
|
+
window.removeEventListener('mousemove', handleMouseMove);
|
|
43
|
+
window.removeEventListener('mouseup', handleMouseUp);
|
|
44
|
+
}
|
|
45
|
+
function handleMouseMove(e) {
|
|
46
|
+
if (!dragging)
|
|
47
|
+
return;
|
|
48
|
+
const endPoint = localPoint(svgEl, e);
|
|
49
|
+
const deltaX = endPoint.x - startPoint.x;
|
|
50
|
+
const deltaY = endPoint.y - startPoint.y;
|
|
51
|
+
translate.set({
|
|
52
|
+
x: startTranslate.x + deltaX / $scale.x,
|
|
53
|
+
y: startTranslate.y + deltaY / $scale.y
|
|
54
|
+
}, { hard: true });
|
|
55
|
+
}
|
|
56
|
+
function handleDoubleClick() {
|
|
57
|
+
increase();
|
|
58
|
+
}
|
|
59
|
+
function handleWheel(e) {
|
|
60
|
+
e.preventDefault();
|
|
61
|
+
const scaleBy = -e.deltaY > 0 ? 1.1 : 0.9;
|
|
62
|
+
// TODO: Update to match d3-zoom delta
|
|
63
|
+
// https://github.com/d3/d3-zoom#zoom_wheelDelta
|
|
64
|
+
// const scaleBy = -e.deltaY * (e.deltaMode === 1 ? 0.05 : e.deltaMode ? 1 : 0.002);
|
|
65
|
+
scale.set({
|
|
66
|
+
x: $scale.x * scaleBy,
|
|
67
|
+
y: $scale.y * scaleBy
|
|
68
|
+
}, { hard: true });
|
|
69
|
+
}
|
|
70
|
+
function localPoint(svgEl, e) {
|
|
71
|
+
const screenCTM = svgEl.getScreenCTM();
|
|
72
|
+
const coords = {
|
|
73
|
+
x: e.clientX,
|
|
74
|
+
y: e.clientY
|
|
75
|
+
};
|
|
76
|
+
let point = svgEl.createSVGPoint();
|
|
77
|
+
point.x = coords.x;
|
|
78
|
+
point.y = coords.y;
|
|
79
|
+
point = point.matrixTransform(screenCTM.inverse());
|
|
80
|
+
return {
|
|
81
|
+
x: point.x,
|
|
82
|
+
y: point.y
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
$: center = { x: $width / 2, y: $height / 2 };
|
|
86
|
+
$: viewportCenter = {
|
|
87
|
+
x: center.x - $translate.x,
|
|
88
|
+
y: center.y - $translate.y
|
|
89
|
+
};
|
|
90
|
+
$: newTranslate = {
|
|
91
|
+
x: $translate.x * $scale.x + center.x - center.x * $scale.x,
|
|
92
|
+
y: $translate.y * $scale.y + center.y - center.y * $scale.y
|
|
93
|
+
};
|
|
94
|
+
</script>
|
|
95
|
+
|
|
96
|
+
<rect
|
|
97
|
+
x={-$padding.left}
|
|
98
|
+
y={-$padding.top}
|
|
99
|
+
width={$width + $padding.left + $padding.right}
|
|
100
|
+
height={$height + $padding.top + $padding.bottom}
|
|
101
|
+
on:mousewheel={handleWheel}
|
|
102
|
+
on:mousedown={handleMouseDown}
|
|
103
|
+
on:dblclick={handleDoubleClick}
|
|
104
|
+
fill="transparent"
|
|
105
|
+
/>
|
|
106
|
+
<g transform="translate({newTranslate.x},{newTranslate.y}) scale({$scale.x},{$scale.y})">
|
|
107
|
+
<slot />
|
|
108
|
+
</g>
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { SvelteComponentTyped } from "svelte";
|
|
2
|
+
declare const __propDef: {
|
|
3
|
+
props: {
|
|
4
|
+
reset?: () => void;
|
|
5
|
+
increase?: () => void;
|
|
6
|
+
decrease?: () => void;
|
|
7
|
+
translateCenter?: () => void;
|
|
8
|
+
};
|
|
9
|
+
events: {
|
|
10
|
+
[evt: string]: CustomEvent<any>;
|
|
11
|
+
};
|
|
12
|
+
slots: {
|
|
13
|
+
default: {};
|
|
14
|
+
};
|
|
15
|
+
};
|
|
16
|
+
export declare type ZoomProps = typeof __propDef.props;
|
|
17
|
+
export declare type ZoomEvents = typeof __propDef.events;
|
|
18
|
+
export declare type ZoomSlots = typeof __propDef.slots;
|
|
19
|
+
export default class Zoom extends SvelteComponentTyped<ZoomProps, ZoomEvents, ZoomSlots> {
|
|
20
|
+
get reset(): () => void;
|
|
21
|
+
get increase(): () => void;
|
|
22
|
+
get decrease(): () => void;
|
|
23
|
+
get translateCenter(): () => void;
|
|
24
|
+
}
|
|
25
|
+
export {};
|
package/components/index.d.ts
CHANGED
|
@@ -6,6 +6,7 @@ export { default as AxisY } from './AxisY.svelte';
|
|
|
6
6
|
export { default as Bars } from './Bars.svelte';
|
|
7
7
|
export { default as Baseline } from './Baseline.svelte';
|
|
8
8
|
export { default as Chart } from './Chart.svelte';
|
|
9
|
+
export { default as ChartClipPath } from './ChartClipPath.svelte';
|
|
9
10
|
export { default as Circle } from './Circle.svelte';
|
|
10
11
|
export { default as CircleClipPath } from './CircleClipPath.svelte';
|
|
11
12
|
export { default as ClipPath } from './ClipPath.svelte';
|
|
@@ -28,3 +29,4 @@ export { default as Text } from './Text.svelte';
|
|
|
28
29
|
export { default as Threshold } from './Threshold.svelte';
|
|
29
30
|
export { default as Tooltip } from './Tooltip.svelte';
|
|
30
31
|
export { default as Treemap } from './Treemap.svelte';
|
|
32
|
+
export { default as Zoom } from './Zoom.svelte';
|
package/components/index.js
CHANGED
|
@@ -6,6 +6,7 @@ export { default as AxisY } from './AxisY.svelte';
|
|
|
6
6
|
export { default as Bars } from './Bars.svelte';
|
|
7
7
|
export { default as Baseline } from './Baseline.svelte';
|
|
8
8
|
export { default as Chart } from './Chart.svelte';
|
|
9
|
+
export { default as ChartClipPath } from './ChartClipPath.svelte';
|
|
9
10
|
export { default as Circle } from './Circle.svelte';
|
|
10
11
|
export { default as CircleClipPath } from './CircleClipPath.svelte';
|
|
11
12
|
export { default as ClipPath } from './ClipPath.svelte';
|
|
@@ -28,3 +29,4 @@ export { default as Text } from './Text.svelte';
|
|
|
28
29
|
export { default as Threshold } from './Threshold.svelte';
|
|
29
30
|
export { default as Tooltip } from './Tooltip.svelte';
|
|
30
31
|
export { default as Treemap } from './Treemap.svelte';
|
|
32
|
+
export { default as Zoom } from './Zoom.svelte';
|
package/docs/Preview.svelte
CHANGED
package/package.json
CHANGED
|
@@ -3,39 +3,38 @@
|
|
|
3
3
|
"author": "Sean Lynch <techniq35@gmail.com>",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"repository": "techniq/layerchart",
|
|
6
|
-
"version": "0.
|
|
6
|
+
"version": "0.5.0",
|
|
7
7
|
"devDependencies": {
|
|
8
8
|
"@rollup/plugin-dsv": "^2.0.3",
|
|
9
|
-
"@sveltejs/adapter-vercel": "^1.0.0-next.
|
|
10
|
-
"@sveltejs/kit": "^1.0.0-next.
|
|
9
|
+
"@sveltejs/adapter-vercel": "^1.0.0-next.58",
|
|
10
|
+
"@sveltejs/kit": "^1.0.0-next.350",
|
|
11
11
|
"@tailwindcss/typography": "^0.5.2",
|
|
12
|
-
"@types/d3-array": "^3.0.
|
|
12
|
+
"@types/d3-array": "^3.0.3",
|
|
13
13
|
"@types/d3-dsv": "^3.0.0",
|
|
14
|
-
"@types/d3-hierarchy": "^3.0
|
|
14
|
+
"@types/d3-hierarchy": "^3.1.0",
|
|
15
15
|
"@types/d3-sankey": "^0.11.2",
|
|
16
16
|
"@types/d3-scale": "^4.0.2",
|
|
17
|
-
"@types/d3-shape": "^3.0
|
|
17
|
+
"@types/d3-shape": "^3.1.0",
|
|
18
18
|
"@types/lodash-es": "^4.17.6",
|
|
19
|
-
"autoprefixer": "^10.4.
|
|
20
|
-
"mdsvex": "^0.10.
|
|
21
|
-
"prettier": "^2.6.
|
|
22
|
-
"prettier-plugin-svelte": "^2.
|
|
19
|
+
"autoprefixer": "^10.4.7",
|
|
20
|
+
"mdsvex": "^0.10.6",
|
|
21
|
+
"prettier": "^2.6.2",
|
|
22
|
+
"prettier-plugin-svelte": "^2.7.0",
|
|
23
23
|
"prism-themes": "^1.9.0",
|
|
24
|
-
"svelte": "^3.
|
|
25
|
-
"svelte-check": "^2.
|
|
26
|
-
"svelte-preprocess": "^4.10.
|
|
27
|
-
"svelte2tsx": "^0.5.
|
|
28
|
-
"tailwindcss": "^3.0
|
|
29
|
-
"
|
|
30
|
-
"
|
|
31
|
-
"typescript": "^4.6.3",
|
|
24
|
+
"svelte": "^3.48.0",
|
|
25
|
+
"svelte-check": "^2.7.2",
|
|
26
|
+
"svelte-preprocess": "^4.10.7",
|
|
27
|
+
"svelte2tsx": "^0.5.10",
|
|
28
|
+
"tailwindcss": "^3.1.0",
|
|
29
|
+
"tslib": "^2.4.0",
|
|
30
|
+
"typescript": "^4.7.3",
|
|
32
31
|
"unist-util-visit": "^4.1.0",
|
|
33
32
|
"vite-plugin-sveld": "^1.0.3"
|
|
34
33
|
},
|
|
35
34
|
"type": "module",
|
|
36
35
|
"dependencies": {
|
|
37
|
-
"@mdi/js": "^6.
|
|
38
|
-
"d3-array": "^3.1.
|
|
36
|
+
"@mdi/js": "^6.7.96",
|
|
37
|
+
"d3-array": "^3.1.6",
|
|
39
38
|
"d3-dsv": "^3.0.1",
|
|
40
39
|
"d3-hierarchy": "^3.1.2",
|
|
41
40
|
"d3-interpolate-path": "^2.2.3",
|
|
@@ -46,7 +45,7 @@
|
|
|
46
45
|
"date-fns": "^2.28.0",
|
|
47
46
|
"layercake": "^6.1.0",
|
|
48
47
|
"lodash-es": "^4.17.21",
|
|
49
|
-
"svelte-ux": "^0.
|
|
48
|
+
"svelte-ux": "^0.5.1"
|
|
50
49
|
},
|
|
51
50
|
"exports": {
|
|
52
51
|
"./package.json": "./package.json",
|
|
@@ -57,7 +56,9 @@
|
|
|
57
56
|
"./components/AxisY.svelte": "./components/AxisY.svelte",
|
|
58
57
|
"./components/Bars.svelte": "./components/Bars.svelte",
|
|
59
58
|
"./components/Baseline.svelte": "./components/Baseline.svelte",
|
|
59
|
+
"./components/Bounds.svelte": "./components/Bounds.svelte",
|
|
60
60
|
"./components/Chart.svelte": "./components/Chart.svelte",
|
|
61
|
+
"./components/ChartClipPath.svelte": "./components/ChartClipPath.svelte",
|
|
61
62
|
"./components/Circle.svelte": "./components/Circle.svelte",
|
|
62
63
|
"./components/CircleClipPath.svelte": "./components/CircleClipPath.svelte",
|
|
63
64
|
"./components/ClipPath.svelte": "./components/ClipPath.svelte",
|
|
@@ -69,6 +70,7 @@
|
|
|
69
70
|
"./components/Line.svelte": "./components/Line.svelte",
|
|
70
71
|
"./components/LinearGradient.svelte": "./components/LinearGradient.svelte",
|
|
71
72
|
"./components/Link.svelte": "./components/Link.svelte",
|
|
73
|
+
"./components/Partition.svelte": "./components/Partition.svelte",
|
|
72
74
|
"./components/Path.svelte": "./components/Path.svelte",
|
|
73
75
|
"./components/Pattern.svelte": "./components/Pattern.svelte",
|
|
74
76
|
"./components/Pie.svelte": "./components/Pie.svelte",
|
|
@@ -79,7 +81,9 @@
|
|
|
79
81
|
"./components/Text.svelte": "./components/Text.svelte",
|
|
80
82
|
"./components/Threshold.svelte": "./components/Threshold.svelte",
|
|
81
83
|
"./components/Tooltip.svelte": "./components/Tooltip.svelte",
|
|
84
|
+
"./components/Tree.svelte": "./components/Tree.svelte",
|
|
82
85
|
"./components/Treemap.svelte": "./components/Treemap.svelte",
|
|
86
|
+
"./components/Zoom.svelte": "./components/Zoom.svelte",
|
|
83
87
|
"./components": "./components/index.js",
|
|
84
88
|
"./docs/Blockquote.svelte": "./docs/Blockquote.svelte",
|
|
85
89
|
"./docs/Code.svelte": "./docs/Code.svelte",
|
package/utils/genData.d.ts
CHANGED
|
@@ -30,3 +30,22 @@ export declare const longData: {
|
|
|
30
30
|
fruit: string;
|
|
31
31
|
value: number;
|
|
32
32
|
}[];
|
|
33
|
+
export declare function getPhyllotaxis({ radius, count, width, height }: {
|
|
34
|
+
radius: any;
|
|
35
|
+
count: any;
|
|
36
|
+
width: any;
|
|
37
|
+
height: any;
|
|
38
|
+
}): {
|
|
39
|
+
x: number;
|
|
40
|
+
y: number;
|
|
41
|
+
}[];
|
|
42
|
+
export declare function getSpiral({ angle, radius, count, width, height }: {
|
|
43
|
+
angle: any;
|
|
44
|
+
radius: any;
|
|
45
|
+
count: any;
|
|
46
|
+
width: any;
|
|
47
|
+
height: any;
|
|
48
|
+
}): {
|
|
49
|
+
x: number;
|
|
50
|
+
y: number;
|
|
51
|
+
}[];
|
package/utils/genData.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { subDays } from 'date-fns';
|
|
2
|
+
import { degreesToRadians, radiansToDegrees } from './math';
|
|
2
3
|
/**
|
|
3
4
|
* Get random number between min (inclusive) and max (exclusive)
|
|
4
5
|
* see: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/random#getting_a_random_number_between_0_inclusive_and_1_exclusive
|
|
@@ -57,3 +58,18 @@ export const longData = [
|
|
|
57
58
|
{ year: '2016', basket: 2, fruit: 'cherries', value: 720 },
|
|
58
59
|
{ year: '2016', basket: 2, fruit: 'dates', value: 400 }
|
|
59
60
|
];
|
|
61
|
+
export function getPhyllotaxis({ radius, count, width, height }) {
|
|
62
|
+
// Phyllotaxis: https://www.youtube.com/watch?v=KWoJgHFYWxY
|
|
63
|
+
const rads = Math.PI * (3 - Math.sqrt(5)); // ~2.4 rads or ~137.5 degrees
|
|
64
|
+
return getSpiral({ angle: radiansToDegrees(rads), radius, count, width, height });
|
|
65
|
+
}
|
|
66
|
+
export function getSpiral({ angle, radius, count, width, height }) {
|
|
67
|
+
return Array.from({ length: count }, (_, i) => {
|
|
68
|
+
const r = radius * Math.sqrt(i);
|
|
69
|
+
const a = degreesToRadians(angle * i);
|
|
70
|
+
return {
|
|
71
|
+
x: width / 2 + r * Math.cos(a),
|
|
72
|
+
y: height / 2 + r * Math.sin(a)
|
|
73
|
+
};
|
|
74
|
+
});
|
|
75
|
+
}
|
package/utils/math.d.ts
CHANGED
package/utils/math.js
CHANGED
package/utils/scales.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { tweened, spring } from 'svelte/motion';
|
|
1
2
|
/**
|
|
2
3
|
* Implemenation for missing `scaleBand().invert()`
|
|
3
4
|
*
|
|
@@ -8,3 +9,19 @@
|
|
|
8
9
|
*/
|
|
9
10
|
export declare function scaleBandInvert(scale: any): (value: any) => any;
|
|
10
11
|
export declare function isScaleBand(scale: any): boolean;
|
|
12
|
+
/**
|
|
13
|
+
* Animate d3-scale as domain and/or range are updated using tweened store
|
|
14
|
+
*/
|
|
15
|
+
export declare function tweenedScale(scale: any, tweenedOptions?: Parameters<typeof tweened>[1]): {
|
|
16
|
+
subscribe: (this: void, run: import("svelte/store").Subscriber<any>, invalidate?: (value?: any) => void) => import("svelte/store").Unsubscriber;
|
|
17
|
+
domain: (values: any) => Promise<void>;
|
|
18
|
+
range: (values: any) => Promise<void>;
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Animate d3-scale as domain and/or range are updated using spring store
|
|
22
|
+
*/
|
|
23
|
+
export declare function springScale(scale: any, springOptions?: Parameters<typeof spring>[1]): {
|
|
24
|
+
subscribe: (this: void, run: import("svelte/store").Subscriber<any>, invalidate?: (value?: any) => void) => import("svelte/store").Unsubscriber;
|
|
25
|
+
domain: (values: any) => Promise<void>;
|
|
26
|
+
range: (values: any) => Promise<void>;
|
|
27
|
+
};
|
package/utils/scales.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { derived } from 'svelte/store';
|
|
2
|
+
import { tweened, spring } from 'svelte/motion';
|
|
1
3
|
/**
|
|
2
4
|
* Implemenation for missing `scaleBand().invert()`
|
|
3
5
|
*
|
|
@@ -19,3 +21,47 @@ export function scaleBandInvert(scale) {
|
|
|
19
21
|
export function isScaleBand(scale) {
|
|
20
22
|
return typeof scale.bandwidth === 'function';
|
|
21
23
|
}
|
|
24
|
+
/**
|
|
25
|
+
* Animate d3-scale as domain and/or range are updated using tweened store
|
|
26
|
+
*/
|
|
27
|
+
export function tweenedScale(scale, tweenedOptions = {}) {
|
|
28
|
+
const tweenedDomain = tweened(undefined, tweenedOptions);
|
|
29
|
+
const tweenedRange = tweened(undefined, tweenedOptions);
|
|
30
|
+
const tweenedScale = derived([tweenedDomain, tweenedRange], ([domain, range]) => {
|
|
31
|
+
const scaleInstance = scale.domain ? scale : scale(); // support `scaleLinear` or `scaleLinear()` (which could have `.interpolate()` and others set)
|
|
32
|
+
if (domain) {
|
|
33
|
+
scaleInstance.domain(domain);
|
|
34
|
+
}
|
|
35
|
+
if (range) {
|
|
36
|
+
scaleInstance.range(range);
|
|
37
|
+
}
|
|
38
|
+
return scaleInstance;
|
|
39
|
+
});
|
|
40
|
+
return {
|
|
41
|
+
subscribe: tweenedScale.subscribe,
|
|
42
|
+
domain: (values) => tweenedDomain.set(values),
|
|
43
|
+
range: (values) => tweenedRange.set(values)
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Animate d3-scale as domain and/or range are updated using spring store
|
|
48
|
+
*/
|
|
49
|
+
export function springScale(scale, springOptions = {}) {
|
|
50
|
+
const springDomain = spring(undefined, springOptions);
|
|
51
|
+
const springRange = spring(undefined, springOptions);
|
|
52
|
+
const tweenedScale = derived([springDomain, springRange], ([domain, range]) => {
|
|
53
|
+
const scaleInstance = scale.domain ? scale : scale(); // support `scaleLinear` or `scaleLinear()` (which could have `.interpolate()` and others set)
|
|
54
|
+
if (domain) {
|
|
55
|
+
scaleInstance.domain(domain);
|
|
56
|
+
}
|
|
57
|
+
if (range) {
|
|
58
|
+
scaleInstance.range(range);
|
|
59
|
+
}
|
|
60
|
+
return scaleInstance;
|
|
61
|
+
});
|
|
62
|
+
return {
|
|
63
|
+
subscribe: tweenedScale.subscribe,
|
|
64
|
+
domain: (values) => springDomain.set(values),
|
|
65
|
+
range: (values) => springRange.set(values)
|
|
66
|
+
};
|
|
67
|
+
}
|