svelteplot 0.8.1-pr-283.3 → 0.8.1-pr-283.5

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.
@@ -107,7 +107,14 @@
107
107
  {@const groupedTrailData = groupIndex(scaledData, groupByKey)}
108
108
  {#if canvas}
109
109
  <!-- todo -->
110
- <TrailCanvas />
110
+ <TrailCanvas
111
+ {curve}
112
+ {cap}
113
+ {tension}
114
+ {resolution}
115
+ {usedScales}
116
+ data={groupedTrailData}
117
+ options={args} />
111
118
  {:else}
112
119
  <g class={['trail', className]}>
113
120
  {#each groupedTrailData as trailData, i (i)}
@@ -0,0 +1,140 @@
1
+ <script lang="ts" generics="Datum extends DataRecord">
2
+ import type {
3
+ Mark,
4
+ BaseMarkProps,
5
+ PlotContext,
6
+ ScaledDataRecord,
7
+ UsedScales,
8
+ CurveName,
9
+ ConstantAccessor
10
+ } from '../../types/index.js';
11
+ import CanvasLayer from './CanvasLayer.svelte';
12
+ import type { Attachment } from 'svelte/attachments';
13
+ import { devicePixelRatio } from 'svelte/reactivity/window';
14
+ import { resolveColor } from './canvas.js';
15
+ import { getContext } from 'svelte';
16
+ import type { CurveFactory } from 'd3-shape';
17
+ import { trailPath, type TrailSample } from './trail';
18
+ import { resolveProp, resolveScaledStyleProps } from '../../helpers/resolve';
19
+
20
+ interface TrailCanvasProps<Datum> {
21
+ curve?: CurveName | CurveFactory;
22
+ tension?: number;
23
+ cap?: 'butt' | 'round';
24
+ resolution?: number | 'auto';
25
+ data: ScaledDataRecord<Datum>[][];
26
+ usedScales: UsedScales;
27
+ options: {
28
+ fill?: ConstantAccessor<string, Datum>;
29
+ defined?: ConstantAccessor<boolean, Datum>;
30
+ opacity?: ConstantAccessor<number, Datum>;
31
+ 'fill-opacity'?: ConstantAccessor<number, Datum>;
32
+ };
33
+ }
34
+
35
+ let {
36
+ curve,
37
+ cap,
38
+ tension,
39
+ resolution,
40
+ usedScales,
41
+ data: groupedTrailData,
42
+ options
43
+ }: TrailCanvasProps<Datum> = $props();
44
+
45
+ function maybeOpacity(value: unknown) {
46
+ return value == null ? 1 : +value;
47
+ }
48
+
49
+ const { getPlotState } = getContext<PlotContext>('svelteplot');
50
+ const plot = $derived(getPlotState());
51
+
52
+ const render = ((canvas: HTMLCanvasElement) => {
53
+ const context = canvas.getContext('2d');
54
+
55
+ $effect(() => {
56
+ if (context) {
57
+ context.resetTransform();
58
+ context.scale(devicePixelRatio.current ?? 1, devicePixelRatio.current ?? 1);
59
+
60
+ for (const trailData of groupedTrailData) {
61
+ if (trailData.length < 2) continue;
62
+
63
+ // Get the first point to determine line styles
64
+ const firstPoint = trailData[0];
65
+ if (!firstPoint || !firstPoint.valid) continue;
66
+
67
+ const samples = trailData.map((d) => ({
68
+ x: Number(d.x),
69
+ y: Number(d.y),
70
+ r: Number(d.r ?? 0)
71
+ })) satisfies TrailSample[];
72
+
73
+ const defined = trailData.map(
74
+ (d) =>
75
+ d.valid &&
76
+ d.r >= 0 &&
77
+ (resolveProp(options.defined, d.datum, true) ?? true)
78
+ );
79
+
80
+ let { fill, ...restStyles } = resolveScaledStyleProps(
81
+ firstPoint.datum,
82
+ options,
83
+ usedScales,
84
+ plot,
85
+ 'fill'
86
+ );
87
+
88
+ const opacity = maybeOpacity(restStyles['opacity']);
89
+ const fillOpacity = maybeOpacity(restStyles['fill-opacity']);
90
+
91
+ fill = resolveColor(fill, canvas);
92
+
93
+ context.fillStyle = fill ? fill : 'currentColor';
94
+ context.beginPath();
95
+
96
+ trailPath(samples, defined, context, {
97
+ curve,
98
+ cap,
99
+ tension,
100
+ ...(typeof resolution === 'number' ? { samplesPerSegment: resolution } : {})
101
+ });
102
+
103
+ context.globalAlpha = opacity * fillOpacity;
104
+ context.fill();
105
+
106
+ // {#each groupedTrailData as trailData, i (i)}
107
+ // {@const samples = trailData.map((d) => ({
108
+ // x: Number(d.x),
109
+ // y: Number(d.y),
110
+ // r: Number(d.r ?? 0)
111
+ // })) satisfies TrailSample[]}
112
+ // {@const defined = trailData.map(
113
+ // (d) =>
114
+ // d.valid &&
115
+ // d.r >= 0 &&
116
+ // (resolveProp(options.defined, d.datum, true) ?? true)
117
+ // )}
118
+ // {@const pathString = trailPath(samples, defined, d3Path(), {
119
+ // curve,
120
+ // cap,
121
+ // tension,
122
+ // ...(typeof resolution === 'number'
123
+ // ? { samplesPerSegment: resolution }
124
+ // : {})
125
+ }
126
+ }
127
+
128
+ return () => {
129
+ context?.clearRect(
130
+ 0,
131
+ 0,
132
+ plot.width * (devicePixelRatio.current ?? 1),
133
+ plot.height * (devicePixelRatio.current ?? 1)
134
+ );
135
+ };
136
+ });
137
+ }) as Attachment;
138
+ </script>
139
+
140
+ <CanvasLayer {@attach render} />
@@ -1,26 +1,40 @@
1
- export default TrailCanvas;
2
- type TrailCanvas = SvelteComponent<{
3
- [x: string]: never;
4
- }, {
5
- [evt: string]: CustomEvent<any>;
6
- }, {}> & {
7
- $$bindings?: string | undefined;
8
- };
9
- declare const TrailCanvas: $$__sveltets_2_IsomorphicComponent<{
10
- [x: string]: never;
11
- }, {
12
- [evt: string]: CustomEvent<any>;
13
- }, {}, {}, string>;
14
- interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
15
- new (options: import("svelte").ComponentConstructorOptions<Props>): import("svelte").SvelteComponent<Props, Events, Slots> & {
16
- $$bindings?: Bindings;
17
- } & Exports;
18
- (internal: unknown, props: {
19
- $$events?: Events;
20
- $$slots?: Slots;
21
- }): Exports & {
22
- $set?: any;
23
- $on?: any;
1
+ import type { ScaledDataRecord, UsedScales, CurveName, ConstantAccessor } from '../../types/index.js';
2
+ import type { CurveFactory } from 'd3-shape';
3
+ interface TrailCanvasProps<Datum> {
4
+ curve?: CurveName | CurveFactory;
5
+ tension?: number;
6
+ cap?: 'butt' | 'round';
7
+ resolution?: number | 'auto';
8
+ data: ScaledDataRecord<Datum>[][];
9
+ usedScales: UsedScales;
10
+ options: {
11
+ fill?: ConstantAccessor<string, Datum>;
12
+ defined?: ConstantAccessor<boolean, Datum>;
13
+ opacity?: ConstantAccessor<number, Datum>;
14
+ 'fill-opacity'?: ConstantAccessor<number, Datum>;
24
15
  };
25
- z_$$bindings?: Bindings;
26
16
  }
17
+ declare function $$render<Datum extends DataRecord>(): {
18
+ props: TrailCanvasProps<Datum>;
19
+ exports: {};
20
+ bindings: "";
21
+ slots: {};
22
+ events: {};
23
+ };
24
+ declare class __sveltets_Render<Datum extends DataRecord> {
25
+ props(): ReturnType<typeof $$render<Datum>>['props'];
26
+ events(): ReturnType<typeof $$render<Datum>>['events'];
27
+ slots(): ReturnType<typeof $$render<Datum>>['slots'];
28
+ bindings(): "";
29
+ exports(): {};
30
+ }
31
+ interface $$IsomorphicComponent {
32
+ new <Datum extends DataRecord>(options: import('svelte').ComponentConstructorOptions<ReturnType<__sveltets_Render<Datum>['props']>>): import('svelte').SvelteComponent<ReturnType<__sveltets_Render<Datum>['props']>, ReturnType<__sveltets_Render<Datum>['events']>, ReturnType<__sveltets_Render<Datum>['slots']>> & {
33
+ $$bindings?: ReturnType<__sveltets_Render<Datum>['bindings']>;
34
+ } & ReturnType<__sveltets_Render<Datum>['exports']>;
35
+ <Datum extends DataRecord>(internal: unknown, props: ReturnType<__sveltets_Render<Datum>['props']> & {}): ReturnType<__sveltets_Render<Datum>['exports']>;
36
+ z_$$bindings?: ReturnType<__sveltets_Render<any>['bindings']>;
37
+ }
38
+ declare const TrailCanvas: $$IsomorphicComponent;
39
+ type TrailCanvas<Datum extends DataRecord> = InstanceType<typeof TrailCanvas<Datum>>;
40
+ export default TrailCanvas;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "svelteplot",
3
- "version": "0.8.1-pr-283.3",
3
+ "version": "0.8.1-pr-283.5",
4
4
  "license": "ISC",
5
5
  "author": {
6
6
  "name": "Gregor Aisch",