svelteplot 0.0.1-alpha.9 → 0.1.3-next.3
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/LICENSE.md +5 -0
- package/README.md +3 -36
- package/dist/Mark.svelte +292 -0
- package/dist/Mark.svelte.d.ts +22 -0
- package/dist/Plot.svelte +148 -156
- package/dist/Plot.svelte.d.ts +15 -15
- package/dist/constants.d.ts +14 -0
- package/dist/constants.js +109 -0
- package/dist/core/Facet.svelte +59 -0
- package/dist/core/Facet.svelte.d.ts +18 -0
- package/dist/core/FacetAxes.svelte +66 -0
- package/dist/core/FacetAxes.svelte.d.ts +4 -0
- package/dist/core/FacetGrid.svelte +86 -0
- package/dist/core/FacetGrid.svelte.d.ts +13 -0
- package/dist/core/Plot.svelte +567 -0
- package/dist/core/Plot.svelte.d.ts +14 -0
- package/dist/helpers/arrowPath.d.ts +14 -0
- package/dist/helpers/arrowPath.js +129 -0
- package/dist/helpers/autoProjection.d.ts +19 -0
- package/dist/helpers/autoProjection.js +87 -0
- package/dist/helpers/autoScales.d.ts +23 -0
- package/dist/helpers/autoScales.js +203 -0
- package/dist/helpers/autoTicks.d.ts +3 -0
- package/dist/helpers/autoTicks.js +40 -0
- package/dist/helpers/autoTimeFormat.d.ts +2 -2
- package/dist/helpers/autoTimeFormat.js +34 -5
- package/dist/helpers/callWithProps.d.ts +8 -0
- package/dist/helpers/callWithProps.js +13 -0
- package/dist/helpers/colors.js +17 -2
- package/dist/helpers/curves.d.ts +3 -0
- package/dist/helpers/curves.js +42 -0
- package/dist/helpers/data.d.ts +9 -0
- package/dist/helpers/data.js +16 -0
- package/dist/helpers/facets.d.ts +12 -0
- package/dist/helpers/facets.js +49 -0
- package/dist/helpers/formats.d.ts +3 -0
- package/dist/helpers/formats.js +3 -0
- package/dist/helpers/getBaseStyles.d.ts +7 -2
- package/dist/helpers/getBaseStyles.js +34 -10
- package/dist/helpers/getLogTicks.js +5 -5
- package/dist/helpers/group.d.ts +6 -0
- package/dist/helpers/group.js +53 -0
- package/dist/helpers/index.d.ts +18 -0
- package/dist/helpers/index.js +53 -0
- package/dist/helpers/isRawValue.d.ts +2 -0
- package/dist/helpers/isRawValue.js +5 -0
- package/dist/helpers/isValid.d.ts +6 -0
- package/dist/helpers/isValid.js +6 -0
- package/dist/helpers/math.d.ts +19 -0
- package/dist/helpers/math.js +116 -0
- package/dist/helpers/mergeDeep.d.ts +1 -1
- package/dist/helpers/noise.d.ts +1 -0
- package/dist/helpers/noise.js +72 -0
- package/dist/helpers/projection.d.ts +33 -0
- package/dist/helpers/projection.js +100 -0
- package/dist/helpers/reduce.d.ts +10 -0
- package/dist/helpers/reduce.js +85 -0
- package/dist/helpers/regressionLoess.d.ts +12 -0
- package/dist/helpers/regressionLoess.js +47 -0
- package/dist/helpers/removeIdenticalLines.d.ts +8 -1
- package/dist/helpers/removeIdenticalLines.js +14 -7
- package/dist/helpers/resolve.d.ts +17 -0
- package/dist/helpers/resolve.js +152 -0
- package/dist/helpers/roundedRect.d.ts +9 -0
- package/dist/helpers/roundedRect.js +31 -0
- package/dist/helpers/scales.d.ts +42 -0
- package/dist/helpers/scales.js +309 -0
- package/dist/helpers/time.d.ts +6 -0
- package/dist/helpers/time.js +282 -0
- package/dist/helpers/typeChecks.d.ts +8 -5
- package/dist/helpers/typeChecks.js +27 -6
- package/dist/index.d.ts +49 -1
- package/dist/index.js +53 -2
- package/dist/marks/Area.svelte +146 -0
- package/dist/marks/Area.svelte.d.ts +30 -0
- package/dist/marks/AreaX.svelte +27 -0
- package/dist/marks/AreaX.svelte.d.ts +12 -0
- package/dist/marks/AreaY.svelte +38 -0
- package/dist/marks/AreaY.svelte.d.ts +19 -0
- package/dist/marks/Arrow.svelte +139 -0
- package/dist/marks/Arrow.svelte.d.ts +44 -0
- package/dist/marks/AxisX.svelte +198 -93
- package/dist/marks/AxisX.svelte.d.ts +17 -16
- package/dist/marks/AxisY.svelte +176 -62
- package/dist/marks/AxisY.svelte.d.ts +17 -14
- package/dist/marks/BarX.svelte +81 -0
- package/dist/marks/BarX.svelte.d.ts +4 -0
- package/dist/marks/BarY.svelte +95 -0
- package/dist/marks/BarY.svelte.d.ts +4 -0
- package/dist/marks/BollingerX.svelte +44 -0
- package/dist/marks/BollingerX.svelte.d.ts +18 -0
- package/dist/marks/BollingerY.svelte +39 -0
- package/dist/marks/BollingerY.svelte.d.ts +18 -0
- package/dist/marks/BoxX.svelte +89 -0
- package/dist/marks/BoxX.svelte.d.ts +4 -0
- package/dist/marks/BoxY.svelte +110 -0
- package/dist/marks/BoxY.svelte.d.ts +29 -0
- package/dist/marks/Cell.svelte +110 -0
- package/dist/marks/Cell.svelte.d.ts +16 -0
- package/dist/marks/CellX.svelte +24 -0
- package/dist/marks/CellX.svelte.d.ts +3 -0
- package/dist/marks/CellY.svelte +24 -0
- package/dist/marks/CellY.svelte.d.ts +3 -0
- package/dist/marks/ColorLegend.svelte +148 -27
- package/dist/marks/ColorLegend.svelte.d.ts +12 -13
- package/dist/marks/CustomMark.svelte +43 -0
- package/dist/marks/CustomMark.svelte.d.ts +16 -0
- package/dist/marks/CustomMarkHTML.svelte +103 -0
- package/dist/marks/CustomMarkHTML.svelte.d.ts +17 -0
- package/dist/marks/DifferenceY.svelte +144 -0
- package/dist/marks/DifferenceY.svelte.d.ts +30 -0
- package/dist/marks/Dot.svelte +128 -73
- package/dist/marks/Dot.svelte.d.ts +24 -14
- package/dist/marks/DotX.svelte +15 -3
- package/dist/marks/DotX.svelte.d.ts +8 -16
- package/dist/marks/DotY.svelte +8 -3
- package/dist/marks/DotY.svelte.d.ts +5 -17
- package/dist/marks/Frame.svelte +32 -31
- package/dist/marks/Frame.svelte.d.ts +7 -14
- package/dist/marks/Geo.svelte +102 -0
- package/dist/marks/Geo.svelte.d.ts +10 -0
- package/dist/marks/Graticule.svelte +28 -0
- package/dist/marks/Graticule.svelte.d.ts +9 -0
- package/dist/marks/GridX.svelte +67 -36
- package/dist/marks/GridX.svelte.d.ts +7 -18
- package/dist/marks/GridY.svelte +64 -25
- package/dist/marks/GridY.svelte.d.ts +7 -14
- package/dist/marks/HTMLTooltip.svelte +91 -0
- package/dist/marks/HTMLTooltip.svelte.d.ts +11 -0
- package/dist/marks/Line.svelte +219 -58
- package/dist/marks/Line.svelte.d.ts +30 -14
- package/dist/marks/LineX.svelte +8 -8
- package/dist/marks/LineX.svelte.d.ts +4 -17
- package/dist/marks/LineY.svelte +7 -8
- package/dist/marks/LineY.svelte.d.ts +4 -17
- package/dist/marks/Link.svelte +173 -0
- package/dist/marks/Link.svelte.d.ts +21 -0
- package/dist/marks/Pointer.svelte +126 -0
- package/dist/marks/Pointer.svelte.d.ts +23 -0
- package/dist/marks/Rect.svelte +103 -0
- package/dist/marks/Rect.svelte.d.ts +15 -0
- package/dist/marks/RectX.svelte +33 -0
- package/dist/marks/RectX.svelte.d.ts +15 -0
- package/dist/marks/RectY.svelte +33 -0
- package/dist/marks/RectY.svelte.d.ts +15 -0
- package/dist/marks/RegressionX.svelte +26 -0
- package/dist/marks/RegressionX.svelte.d.ts +4 -0
- package/dist/marks/RegressionY.svelte +26 -0
- package/dist/marks/RegressionY.svelte.d.ts +4 -0
- package/dist/marks/RuleX.svelte +52 -28
- package/dist/marks/RuleX.svelte.d.ts +14 -14
- package/dist/marks/RuleY.svelte +52 -28
- package/dist/marks/RuleY.svelte.d.ts +14 -14
- package/dist/marks/Sphere.svelte +8 -0
- package/dist/marks/Sphere.svelte.d.ts +51 -0
- package/dist/marks/Spike.svelte +15 -0
- package/dist/marks/Spike.svelte.d.ts +4 -0
- package/dist/marks/SymbolLegend.svelte +27 -12
- package/dist/marks/SymbolLegend.svelte.d.ts +8 -14
- package/dist/marks/Text.svelte +185 -0
- package/dist/marks/Text.svelte.d.ts +26 -0
- package/dist/marks/TickX.svelte +89 -0
- package/dist/marks/TickX.svelte.d.ts +22 -0
- package/dist/marks/TickY.svelte +90 -0
- package/dist/marks/TickY.svelte.d.ts +22 -0
- package/dist/marks/Vector.svelte +213 -0
- package/dist/marks/Vector.svelte.d.ts +31 -0
- package/dist/marks/helpers/BaseAxisX.svelte +210 -0
- package/dist/marks/helpers/BaseAxisX.svelte.d.ts +24 -0
- package/dist/marks/helpers/BaseAxisY.svelte +187 -0
- package/dist/marks/helpers/BaseAxisY.svelte.d.ts +23 -0
- package/dist/marks/helpers/CanvasLayer.svelte +38 -0
- package/dist/marks/helpers/CanvasLayer.svelte.d.ts +13 -0
- package/dist/marks/helpers/DotCanvas.svelte +184 -0
- package/dist/marks/helpers/DotCanvas.svelte.d.ts +11 -0
- package/dist/marks/helpers/GeoCanvas.svelte +165 -0
- package/dist/marks/helpers/GeoCanvas.svelte.d.ts +13 -0
- package/dist/marks/helpers/GroupMultiple.svelte +17 -0
- package/dist/marks/helpers/GroupMultiple.svelte.d.ts +9 -0
- package/dist/marks/helpers/Marker.svelte +93 -0
- package/dist/marks/helpers/Marker.svelte.d.ts +10 -0
- package/dist/marks/helpers/MarkerPath.svelte +164 -0
- package/dist/marks/helpers/MarkerPath.svelte.d.ts +44 -0
- package/dist/marks/helpers/Regression.svelte +174 -0
- package/dist/marks/helpers/Regression.svelte.d.ts +26 -0
- package/dist/marks/helpers/events.d.ts +8 -0
- package/dist/marks/helpers/events.js +64 -0
- package/dist/transforms/bin.d.ts +51 -0
- package/dist/transforms/bin.js +171 -0
- package/dist/transforms/bollinger.d.ts +21 -0
- package/dist/transforms/bollinger.js +53 -0
- package/dist/transforms/centroid.d.ts +9 -0
- package/dist/transforms/centroid.js +13 -0
- package/dist/transforms/facet.d.ts +1 -0
- package/dist/transforms/facet.js +1 -0
- package/dist/transforms/filter.d.ts +2 -0
- package/dist/transforms/filter.js +8 -0
- package/dist/transforms/group.d.ts +66 -0
- package/dist/transforms/group.js +109 -0
- package/dist/transforms/interval.d.ts +11 -0
- package/dist/transforms/interval.js +34 -0
- package/dist/transforms/jitter.d.ts +0 -0
- package/dist/transforms/jitter.js +1 -0
- package/dist/transforms/map.d.ts +10 -0
- package/dist/transforms/map.js +89 -0
- package/dist/transforms/normalize.d.ts +9 -0
- package/dist/transforms/normalize.js +86 -0
- package/dist/transforms/recordize.d.ts +13 -0
- package/dist/transforms/recordize.js +75 -0
- package/dist/transforms/rename.d.ts +14 -0
- package/dist/transforms/rename.js +42 -0
- package/dist/transforms/select.d.ts +35 -0
- package/dist/transforms/select.js +55 -0
- package/dist/transforms/shift.d.ts +13 -0
- package/dist/transforms/shift.js +45 -0
- package/dist/transforms/sort.d.ts +28 -0
- package/dist/transforms/sort.js +61 -0
- package/dist/transforms/stack.d.ts +10 -0
- package/dist/transforms/stack.js +110 -0
- package/dist/transforms/window.d.ts +22 -0
- package/dist/transforms/window.js +73 -0
- package/dist/types.d.ts +625 -188
- package/dist/ui/Checkbox.svelte +6 -0
- package/dist/ui/Checkbox.svelte.d.ts +13 -0
- package/dist/ui/RadioInput.svelte +27 -0
- package/dist/ui/RadioInput.svelte.d.ts +9 -0
- package/dist/ui/Select.svelte +27 -0
- package/dist/ui/Select.svelte.d.ts +9 -0
- package/dist/ui/Slider.svelte +47 -0
- package/dist/ui/Slider.svelte.d.ts +11 -0
- package/dist/ui/Spiral.svelte +46 -0
- package/dist/ui/Spiral.svelte.d.ts +15 -0
- package/dist/ui/index.d.ts +4 -0
- package/dist/ui/index.js +4 -0
- package/package.json +79 -40
- package/LICENSE +0 -11
- package/dist/classes/Channel.svelte.js +0 -74
- package/dist/classes/Mark.svelte.js +0 -17
- package/dist/classes/Plot.svelte.js +0 -98
- package/dist/contants.d.ts +0 -3
- package/dist/contants.js +0 -40
- package/dist/helpers/GroupMultiple.svelte +0 -8
- package/dist/helpers/GroupMultiple.svelte.d.ts +0 -19
- package/dist/helpers/createScale.d.ts +0 -5
- package/dist/helpers/createScale.js +0 -57
- package/dist/helpers/resolveChannel.d.ts +0 -2
- package/dist/helpers/resolveChannel.js +0 -28
- package/dist/helpers/wrapArray.d.ts +0 -2
- package/dist/helpers/wrapArray.js +0 -4
- package/dist/marks/BaseMark.svelte +0 -22
- package/dist/marks/BaseMark.svelte.d.ts +0 -19
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { getContext, type Snippet } from 'svelte';
|
|
3
|
+
import GroupMultiple from './helpers/GroupMultiple.svelte';
|
|
4
|
+
import type {
|
|
5
|
+
PlotContext,
|
|
6
|
+
DataRecord,
|
|
7
|
+
BaseMarkProps,
|
|
8
|
+
ConstantAccessor,
|
|
9
|
+
ChannelAccessor
|
|
10
|
+
} from '../types.js';
|
|
11
|
+
import { resolveProp, resolveStyles } from '../helpers/resolve.js';
|
|
12
|
+
import Mark from '../Mark.svelte';
|
|
13
|
+
import { sort } from '../index.js';
|
|
14
|
+
|
|
15
|
+
type TextMarkProps = BaseMarkProps & {
|
|
16
|
+
data: DataRecord[];
|
|
17
|
+
x: ChannelAccessor;
|
|
18
|
+
y: ChannelAccessor;
|
|
19
|
+
fill?: ChannelAccessor;
|
|
20
|
+
stroke?: ChannelAccessor;
|
|
21
|
+
children?: Snippet;
|
|
22
|
+
dx?: ConstantAccessor<number>;
|
|
23
|
+
dy?: ConstantAccessor<number>;
|
|
24
|
+
text: ConstantAccessor<string>;
|
|
25
|
+
title: ConstantAccessor<string>;
|
|
26
|
+
/**
|
|
27
|
+
* if you want to apply class names to individual text elements
|
|
28
|
+
*/
|
|
29
|
+
textClass: ConstantAccessor<string>;
|
|
30
|
+
/**
|
|
31
|
+
* the line anchor for vertical position; top, bottom, or middle
|
|
32
|
+
*/
|
|
33
|
+
lineAnchor?: ConstantAccessor<'bottom' | 'top' | 'middle'>;
|
|
34
|
+
frameAnchor?: ConstantAccessor<
|
|
35
|
+
| 'bottom'
|
|
36
|
+
| 'top'
|
|
37
|
+
| 'left'
|
|
38
|
+
| 'right'
|
|
39
|
+
| 'top-left'
|
|
40
|
+
| 'bottom-left'
|
|
41
|
+
| 'top-right'
|
|
42
|
+
| 'bottom-right'
|
|
43
|
+
>;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
let { data = [{}], class: className = null, ...options }: TextMarkProps = $props();
|
|
47
|
+
|
|
48
|
+
const { getPlotState } = getContext<PlotContext>('svelteplot');
|
|
49
|
+
let plot = $derived(getPlotState());
|
|
50
|
+
|
|
51
|
+
const LINE_ANCHOR = {
|
|
52
|
+
bottom: 'auto',
|
|
53
|
+
middle: 'central',
|
|
54
|
+
top: 'hanging'
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
const args = $derived(
|
|
58
|
+
sort({
|
|
59
|
+
data,
|
|
60
|
+
...options
|
|
61
|
+
})
|
|
62
|
+
);
|
|
63
|
+
</script>
|
|
64
|
+
|
|
65
|
+
<Mark
|
|
66
|
+
type="text"
|
|
67
|
+
channels={[
|
|
68
|
+
'x',
|
|
69
|
+
'y',
|
|
70
|
+
'r',
|
|
71
|
+
'symbol',
|
|
72
|
+
'fill',
|
|
73
|
+
'stroke',
|
|
74
|
+
'opacity',
|
|
75
|
+
'strokeOpacity',
|
|
76
|
+
'fillOpacity'
|
|
77
|
+
]}
|
|
78
|
+
{...args}>
|
|
79
|
+
{#snippet children({ mark, scaledData, usedScales })}
|
|
80
|
+
<GroupMultiple class="text {className || null}" length={className ? 2 : args.data.length}>
|
|
81
|
+
{#each scaledData as d}
|
|
82
|
+
{#if d.valid}
|
|
83
|
+
{@const title = resolveProp(args.title, d.datum, '')}
|
|
84
|
+
{@const frameAnchor = resolveProp(args.frameAnchor, d.datum)}
|
|
85
|
+
{@const isLeft =
|
|
86
|
+
frameAnchor === 'left' ||
|
|
87
|
+
frameAnchor === 'top-left' ||
|
|
88
|
+
frameAnchor === 'bottom-left'}
|
|
89
|
+
{@const isRight =
|
|
90
|
+
frameAnchor === 'right' ||
|
|
91
|
+
frameAnchor === 'top-right' ||
|
|
92
|
+
frameAnchor === 'bottom-right'}
|
|
93
|
+
{@const isTop =
|
|
94
|
+
frameAnchor === 'top' ||
|
|
95
|
+
frameAnchor === 'top-left' ||
|
|
96
|
+
frameAnchor === 'top-right'}
|
|
97
|
+
{@const isBottom =
|
|
98
|
+
frameAnchor === 'bottom' ||
|
|
99
|
+
frameAnchor === 'bottom-left' ||
|
|
100
|
+
frameAnchor === 'bottom-right'}
|
|
101
|
+
{@const [x, y] =
|
|
102
|
+
args.x != null && args.y != null
|
|
103
|
+
? [d.x, d.y]
|
|
104
|
+
: [
|
|
105
|
+
args.x != null
|
|
106
|
+
? d.x
|
|
107
|
+
: isLeft
|
|
108
|
+
? plot.options.marginLeft
|
|
109
|
+
: isRight
|
|
110
|
+
? plot.options.marginLeft + plot.facetWidth
|
|
111
|
+
: plot.options.marginLeft + plot.facetWidth * 0.5,
|
|
112
|
+
args.y != null
|
|
113
|
+
? d.y
|
|
114
|
+
: isTop
|
|
115
|
+
? plot.options.marginTop
|
|
116
|
+
: isBottom
|
|
117
|
+
? plot.options.marginTop + plot.facetHeight
|
|
118
|
+
: plot.options.marginTop + plot.facetHeight * 0.5
|
|
119
|
+
]}
|
|
120
|
+
|
|
121
|
+
{@const dx = +resolveProp(args.dx, d.datum, 0)}
|
|
122
|
+
{@const dy = +resolveProp(args.dy, d.datum, 0)}
|
|
123
|
+
{@const textLines = String(resolveProp(args.text, d.datum, '')).split('\n')}
|
|
124
|
+
{@const lineAnchor = resolveProp(
|
|
125
|
+
args.lineAnchor,
|
|
126
|
+
d.datum,
|
|
127
|
+
args.y != null ? 'middle' : isTop ? 'top' : isBottom ? 'bottom' : 'middle'
|
|
128
|
+
)}
|
|
129
|
+
{@const textClassName = resolveProp(args.textClass, d.datum, null)}
|
|
130
|
+
|
|
131
|
+
{@const [style, styleClass] = resolveStyles(
|
|
132
|
+
plot,
|
|
133
|
+
{ ...d, __tspanIndex: 0 },
|
|
134
|
+
{ textAnchor: isLeft ? 'start' : isRight ? 'end' : 'middle', ...args },
|
|
135
|
+
'fill',
|
|
136
|
+
usedScales
|
|
137
|
+
)}
|
|
138
|
+
|
|
139
|
+
{#if textLines.length > 1}
|
|
140
|
+
<!-- multiline text-->
|
|
141
|
+
{@const fontSize = resolveProp(args.fontSize, d.datum) || 12}
|
|
142
|
+
<text
|
|
143
|
+
class={[textClassName, styleClass]}
|
|
144
|
+
dominant-baseline={LINE_ANCHOR[lineAnchor]}
|
|
145
|
+
transform="translate({[
|
|
146
|
+
Math.round(x + dx),
|
|
147
|
+
Math.round(
|
|
148
|
+
y +
|
|
149
|
+
dy -
|
|
150
|
+
(lineAnchor === 'bottom'
|
|
151
|
+
? textLines.length - 1
|
|
152
|
+
: lineAnchor === 'middle'
|
|
153
|
+
? (textLines.length - 1) * 0.5
|
|
154
|
+
: 0) *
|
|
155
|
+
fontSize
|
|
156
|
+
)
|
|
157
|
+
]})"
|
|
158
|
+
>{#each textLines as line, l}<tspan x="0" dy={l ? fontSize : 0} {style}
|
|
159
|
+
>{line}</tspan
|
|
160
|
+
>{/each}{#if title}<title>{title}</title>{/if}</text>
|
|
161
|
+
{:else}
|
|
162
|
+
<!-- singleline text-->
|
|
163
|
+
<text
|
|
164
|
+
class={[textClassName, styleClass]}
|
|
165
|
+
dominant-baseline={LINE_ANCHOR[lineAnchor]}
|
|
166
|
+
transform="translate({[Math.round(x + dx), Math.round(y + dy)]})"
|
|
167
|
+
{style}
|
|
168
|
+
>{textLines[0]}{#if title}<title>{title}</title>{/if}</text>
|
|
169
|
+
{/if}
|
|
170
|
+
{/if}
|
|
171
|
+
{/each}
|
|
172
|
+
</GroupMultiple>
|
|
173
|
+
{/snippet}
|
|
174
|
+
</Mark>
|
|
175
|
+
|
|
176
|
+
<style>
|
|
177
|
+
text {
|
|
178
|
+
fill: none;
|
|
179
|
+
stroke: none;
|
|
180
|
+
font-size: 12px;
|
|
181
|
+
font-weight: 500;
|
|
182
|
+
stroke-width: 1.6px;
|
|
183
|
+
paint-order: stroke fill;
|
|
184
|
+
}
|
|
185
|
+
</style>
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { type Snippet } from 'svelte';
|
|
2
|
+
import type { DataRecord, BaseMarkProps, ConstantAccessor, ChannelAccessor } from '../types.js';
|
|
3
|
+
type TextMarkProps = BaseMarkProps & {
|
|
4
|
+
data: DataRecord[];
|
|
5
|
+
x: ChannelAccessor;
|
|
6
|
+
y: ChannelAccessor;
|
|
7
|
+
fill?: ChannelAccessor;
|
|
8
|
+
stroke?: ChannelAccessor;
|
|
9
|
+
children?: Snippet;
|
|
10
|
+
dx?: ConstantAccessor<number>;
|
|
11
|
+
dy?: ConstantAccessor<number>;
|
|
12
|
+
text: ConstantAccessor<string>;
|
|
13
|
+
title: ConstantAccessor<string>;
|
|
14
|
+
/**
|
|
15
|
+
* if you want to apply class names to individual text elements
|
|
16
|
+
*/
|
|
17
|
+
textClass: ConstantAccessor<string>;
|
|
18
|
+
/**
|
|
19
|
+
* the line anchor for vertical position; top, bottom, or middle
|
|
20
|
+
*/
|
|
21
|
+
lineAnchor?: ConstantAccessor<'bottom' | 'top' | 'middle'>;
|
|
22
|
+
frameAnchor?: ConstantAccessor<'bottom' | 'top' | 'left' | 'right' | 'top-left' | 'bottom-left' | 'top-right' | 'bottom-right'>;
|
|
23
|
+
};
|
|
24
|
+
declare const Text: import("svelte").Component<TextMarkProps, {}, "">;
|
|
25
|
+
type Text = ReturnType<typeof Text>;
|
|
26
|
+
export default Text;
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import Mark from '../Mark.svelte';
|
|
3
|
+
import { getContext } from 'svelte';
|
|
4
|
+
import { resolveChannel, resolveProp, resolveScaledStyles } from '../helpers/resolve.js';
|
|
5
|
+
import type {
|
|
6
|
+
PlotContext,
|
|
7
|
+
BaseMarkProps,
|
|
8
|
+
ChannelAccessor,
|
|
9
|
+
DataRow,
|
|
10
|
+
FacetContext
|
|
11
|
+
} from '../types.js';
|
|
12
|
+
import { recordizeX } from '../index.js';
|
|
13
|
+
import { projectX, projectY } from '../helpers/scales.js';
|
|
14
|
+
import { isValid } from '../helpers/isValid.js';
|
|
15
|
+
import { testFilter, parseInset } from '../helpers/index.js';
|
|
16
|
+
|
|
17
|
+
const { getPlotState } = getContext<PlotContext>('svelteplot');
|
|
18
|
+
let plot = $derived(getPlotState());
|
|
19
|
+
|
|
20
|
+
type TickXMarkProps = BaseMarkProps & {
|
|
21
|
+
data: DataRow[];
|
|
22
|
+
/**
|
|
23
|
+
* the horizontal position; bound to the x scale
|
|
24
|
+
*/
|
|
25
|
+
x?: ChannelAccessor;
|
|
26
|
+
/**
|
|
27
|
+
* the vertical position; bound to the y scale, which must be band. If the y channel
|
|
28
|
+
* is not specified, the tick will span the full vertical extent of the frame.
|
|
29
|
+
*/
|
|
30
|
+
y?: ChannelAccessor;
|
|
31
|
+
stroke?: ChannelAccessor;
|
|
32
|
+
/**
|
|
33
|
+
* if ticks are used on a non-bandwidth scale, this will determine the
|
|
34
|
+
* length of the tick. Defaults to 10 pixel
|
|
35
|
+
*/
|
|
36
|
+
tickLength?: ConstantAccessor<number>;
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
let { data = [{}], ...options }: TickXMarkProps = $props();
|
|
40
|
+
|
|
41
|
+
let args = $derived(recordizeX({ data, ...options }, { withIndex: false }));
|
|
42
|
+
|
|
43
|
+
const { getTestFacet } = getContext<FacetContext>('svelteplot/facet');
|
|
44
|
+
let testFacet = $derived(getTestFacet());
|
|
45
|
+
</script>
|
|
46
|
+
|
|
47
|
+
<Mark type="tickX" channels={['x', 'y', 'stroke', 'opacity', 'strokeOpacity']} {...args}>
|
|
48
|
+
{#snippet children({ mark, usedScales })}
|
|
49
|
+
<g class="tick-x">
|
|
50
|
+
{#each args.data as datum}
|
|
51
|
+
{#if testFacet(datum, mark.options) && testFilter(datum, args)}
|
|
52
|
+
{@const x_ = resolveChannel('x', datum, args)}
|
|
53
|
+
{@const y_ = resolveChannel('y', datum, args)}
|
|
54
|
+
{@const inset_ = resolveProp(args.inset, datum, 0)}
|
|
55
|
+
{@const tickLength_ = resolveProp(args.tickLength, datum, 10)}
|
|
56
|
+
{@const dx_ = resolveProp(args.dx, datum, 0)}
|
|
57
|
+
{@const dy_ = resolveProp(args.dy, datum, 0)}
|
|
58
|
+
{#if isValid(x_) && (isValid(y_) || args.y == null) && (args.filter == null || resolveProp(args.filter, datum))}
|
|
59
|
+
{@const x = usedScales.x ? projectX('x', plot.scales, x_) : x_}
|
|
60
|
+
{@const y1 =
|
|
61
|
+
args.y != null
|
|
62
|
+
? usedScales.y
|
|
63
|
+
? projectY('y1', plot.scales, y_)
|
|
64
|
+
: y_
|
|
65
|
+
: plot.options.marginTop}
|
|
66
|
+
{@const y2 =
|
|
67
|
+
args.y != null
|
|
68
|
+
? usedScales.y
|
|
69
|
+
? Number(projectY('y2', plot.scales, y_))
|
|
70
|
+
: y_
|
|
71
|
+
: plot.options.marginTop + plot.plotHeight}
|
|
72
|
+
{@const inset = parseInset(inset_, Math.abs(y2 - y1))}
|
|
73
|
+
<line
|
|
74
|
+
transform="translate({x + dx_}, {dy_})"
|
|
75
|
+
style={resolveScaledStyles(datum, args, usedScales, plot, 'stroke')}
|
|
76
|
+
y1={y1 + inset + (y1 === y2 ? tickLength_ * 0.5 : 0)}
|
|
77
|
+
y2={y2 - inset - (y1 === y2 ? tickLength_ * 0.5 : 0)} />
|
|
78
|
+
{/if}
|
|
79
|
+
{/if}
|
|
80
|
+
{/each}
|
|
81
|
+
</g>
|
|
82
|
+
{/snippet}
|
|
83
|
+
</Mark>
|
|
84
|
+
|
|
85
|
+
<style>
|
|
86
|
+
.tick-x line {
|
|
87
|
+
stroke: currentColor;
|
|
88
|
+
}
|
|
89
|
+
</style>
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { BaseMarkProps, ChannelAccessor, DataRow } from '../types.js';
|
|
2
|
+
type TickXMarkProps = BaseMarkProps & {
|
|
3
|
+
data: DataRow[];
|
|
4
|
+
/**
|
|
5
|
+
* the horizontal position; bound to the x scale
|
|
6
|
+
*/
|
|
7
|
+
x?: ChannelAccessor;
|
|
8
|
+
/**
|
|
9
|
+
* the vertical position; bound to the y scale, which must be band. If the y channel
|
|
10
|
+
* is not specified, the tick will span the full vertical extent of the frame.
|
|
11
|
+
*/
|
|
12
|
+
y?: ChannelAccessor;
|
|
13
|
+
stroke?: ChannelAccessor;
|
|
14
|
+
/**
|
|
15
|
+
* if ticks are used on a non-bandwidth scale, this will determine the
|
|
16
|
+
* length of the tick. Defaults to 10 pixel
|
|
17
|
+
*/
|
|
18
|
+
tickLength?: ConstantAccessor<number>;
|
|
19
|
+
};
|
|
20
|
+
declare const TickX: import("svelte").Component<TickXMarkProps, {}, "">;
|
|
21
|
+
type TickX = ReturnType<typeof TickX>;
|
|
22
|
+
export default TickX;
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import Mark from '../Mark.svelte';
|
|
3
|
+
import { getContext } from 'svelte';
|
|
4
|
+
import { resolveChannel, resolveProp, resolveScaledStyles } from '../helpers/resolve.js';
|
|
5
|
+
import type {
|
|
6
|
+
PlotContext,
|
|
7
|
+
BaseMarkProps,
|
|
8
|
+
ChannelAccessor,
|
|
9
|
+
DataRow,
|
|
10
|
+
FacetContext,
|
|
11
|
+
ConstantAccessor
|
|
12
|
+
} from '../types.js';
|
|
13
|
+
import { recordizeY } from '../index.js';
|
|
14
|
+
import { projectX, projectY } from '../helpers/scales.js';
|
|
15
|
+
import { isValid } from '../helpers/isValid.js';
|
|
16
|
+
import { testFilter, parseInset } from '../helpers/index.js';
|
|
17
|
+
|
|
18
|
+
const { getPlotState } = getContext<PlotContext>('svelteplot');
|
|
19
|
+
let plot = $derived(getPlotState());
|
|
20
|
+
|
|
21
|
+
type TickYMarkProps = BaseMarkProps & {
|
|
22
|
+
data: DataRow[];
|
|
23
|
+
/**
|
|
24
|
+
* the vertical position; bound to the x scale
|
|
25
|
+
*/
|
|
26
|
+
y?: ChannelAccessor;
|
|
27
|
+
/**
|
|
28
|
+
* the horizontal position; bound to the x scale, which must be band. If the x channel
|
|
29
|
+
* is not specified, the tick will span the full horizontal extent of the frame.
|
|
30
|
+
*/
|
|
31
|
+
x?: ChannelAccessor;
|
|
32
|
+
stroke?: ChannelAccessor;
|
|
33
|
+
/**
|
|
34
|
+
* if ticks are used on a non-bandwidth scale, this will determine the
|
|
35
|
+
* length of the tick. Defaults to 10 pixel
|
|
36
|
+
*/
|
|
37
|
+
tickLength?: ConstantAccessor<number>;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
let { data = [{}], ...options }: TickYMarkProps = $props();
|
|
41
|
+
|
|
42
|
+
let args = $derived(recordizeY({ data, ...options }, { withIndex: false }));
|
|
43
|
+
|
|
44
|
+
const { getTestFacet } = getContext<FacetContext>('svelteplot/facet');
|
|
45
|
+
let testFacet = $derived(getTestFacet());
|
|
46
|
+
</script>
|
|
47
|
+
|
|
48
|
+
<Mark type="tickY" channels={['x', 'y', 'stroke', 'opacity', 'strokeOpacity']} {...args}>
|
|
49
|
+
{#snippet children({ mark, usedScales })}
|
|
50
|
+
<g class="tick-y">
|
|
51
|
+
{#each args.data as datum}
|
|
52
|
+
{#if testFacet(datum, mark.options) && testFilter(datum, args)}
|
|
53
|
+
{@const y_ = resolveChannel('y', datum, args)}
|
|
54
|
+
{@const x_ = resolveChannel('x', datum, args)}
|
|
55
|
+
{@const inset_ = resolveProp(args.inset, datum, 0)}
|
|
56
|
+
{@const tickLength_ = resolveProp(args.tickLength, datum, 10)}
|
|
57
|
+
{@const dx_ = resolveProp(args.dx, datum, 0)}
|
|
58
|
+
{@const dy_ = resolveProp(args.dy, datum, 0)}
|
|
59
|
+
{#if isValid(y_) && (isValid(x_) || args.x == null)}
|
|
60
|
+
{@const y = usedScales.y ? projectY('y', plot.scales, y_) : y_}
|
|
61
|
+
{@const x1 =
|
|
62
|
+
args.x != null
|
|
63
|
+
? usedScales.x
|
|
64
|
+
? projectX('x1', plot.scales, x_)
|
|
65
|
+
: x_
|
|
66
|
+
: plot.options.marginLeft}
|
|
67
|
+
{@const x2 =
|
|
68
|
+
args.x != null
|
|
69
|
+
? usedScales.x
|
|
70
|
+
? projectX('x2', plot.scales, x_)
|
|
71
|
+
: x_
|
|
72
|
+
: plot.options.marginLeft + plot.facetWidth}
|
|
73
|
+
{@const inset = parseInset(inset_, Math.abs(x2 - x1))}
|
|
74
|
+
<line
|
|
75
|
+
transform="translate({dx_}, {y + dy_})"
|
|
76
|
+
style={resolveScaledStyles(datum, args, usedScales, plot, 'stroke')}
|
|
77
|
+
x1={x1 + inset + (x1 === x2 ? tickLength_ * 0.5 : 0)}
|
|
78
|
+
x2={x2 - inset - (x1 === x2 ? tickLength_ * 0.5 : 0)} />
|
|
79
|
+
{/if}
|
|
80
|
+
{/if}
|
|
81
|
+
{/each}
|
|
82
|
+
</g>
|
|
83
|
+
{/snippet}
|
|
84
|
+
</Mark>
|
|
85
|
+
|
|
86
|
+
<style>
|
|
87
|
+
.tick-y line {
|
|
88
|
+
stroke: currentColor;
|
|
89
|
+
}
|
|
90
|
+
</style>
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { BaseMarkProps, ChannelAccessor, DataRow, ConstantAccessor } from '../types.js';
|
|
2
|
+
type TickYMarkProps = BaseMarkProps & {
|
|
3
|
+
data: DataRow[];
|
|
4
|
+
/**
|
|
5
|
+
* the vertical position; bound to the x scale
|
|
6
|
+
*/
|
|
7
|
+
y?: ChannelAccessor;
|
|
8
|
+
/**
|
|
9
|
+
* the horizontal position; bound to the x scale, which must be band. If the x channel
|
|
10
|
+
* is not specified, the tick will span the full horizontal extent of the frame.
|
|
11
|
+
*/
|
|
12
|
+
x?: ChannelAccessor;
|
|
13
|
+
stroke?: ChannelAccessor;
|
|
14
|
+
/**
|
|
15
|
+
* if ticks are used on a non-bandwidth scale, this will determine the
|
|
16
|
+
* length of the tick. Defaults to 10 pixel
|
|
17
|
+
*/
|
|
18
|
+
tickLength?: ConstantAccessor<number>;
|
|
19
|
+
};
|
|
20
|
+
declare const TickY: import("svelte").Component<TickYMarkProps, {}, "">;
|
|
21
|
+
type TickY = ReturnType<typeof TickY>;
|
|
22
|
+
export default TickY;
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
<script lang="ts" module>
|
|
2
|
+
import type {
|
|
3
|
+
PlotContext,
|
|
4
|
+
DataRecord,
|
|
5
|
+
BaseMarkProps,
|
|
6
|
+
ConstantAccessor,
|
|
7
|
+
ChannelAccessor,
|
|
8
|
+
FacetContext
|
|
9
|
+
} from '../types.js';
|
|
10
|
+
|
|
11
|
+
type D3Path = ReturnType<typeof import('d3-path').path>;
|
|
12
|
+
|
|
13
|
+
export type ShapeRenderer = {
|
|
14
|
+
draw(context: D3Path, l: number, r: number): void;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export type VectorMarkProps = BaseMarkProps & {
|
|
18
|
+
data: DataRecord[];
|
|
19
|
+
x: ChannelAccessor;
|
|
20
|
+
y: ChannelAccessor;
|
|
21
|
+
r?: number;
|
|
22
|
+
length?: ChannelAccessor;
|
|
23
|
+
rotate?: ChannelAccessor;
|
|
24
|
+
fill?: ChannelAccessor;
|
|
25
|
+
stroke?: ChannelAccessor;
|
|
26
|
+
/**
|
|
27
|
+
* Controls where the vector is anchored in relation to the x, y position.
|
|
28
|
+
* If set to 'start', the arrow will start at the x, y position. If set to
|
|
29
|
+
* 'middle', the arrow will be centered at the x, y position. If set to
|
|
30
|
+
* 'end', the arrow will end at the x, y position.
|
|
31
|
+
*/
|
|
32
|
+
anchor: 'start' | 'middle' | 'end';
|
|
33
|
+
shape?: 'arrow' | 'spike' | 'arrow-filled' | ShapeRenderer;
|
|
34
|
+
children?: Snippet;
|
|
35
|
+
dx?: ConstantAccessor<number>;
|
|
36
|
+
dy?: ConstantAccessor<number>;
|
|
37
|
+
canvas?: boolean;
|
|
38
|
+
};
|
|
39
|
+
</script>
|
|
40
|
+
|
|
41
|
+
<script lang="ts">
|
|
42
|
+
import { getContext, type Snippet } from 'svelte';
|
|
43
|
+
import { pathRound as path } from 'd3-path';
|
|
44
|
+
|
|
45
|
+
import { resolveChannel, resolveProp, resolveStyles } from '../helpers/resolve.js';
|
|
46
|
+
import { projectXY } from '../helpers/scales.js';
|
|
47
|
+
import { sort } from '../index.js';
|
|
48
|
+
import Mark from '../Mark.svelte';
|
|
49
|
+
//import DotCanvas from './helpers/DotCanvas.svelte';
|
|
50
|
+
import { maybeData, testFilter, isValid } from '../helpers/index.js';
|
|
51
|
+
|
|
52
|
+
const defaultRadius = 3.5;
|
|
53
|
+
|
|
54
|
+
// The size of the arrowhead is proportional to its length, but we still allow
|
|
55
|
+
// the relative size of the head to be controlled via the mark’s width option;
|
|
56
|
+
// doubling the default radius will produce an arrowhead that is twice as big.
|
|
57
|
+
// That said, we’ll probably want a arrow with a fixed head size, too.
|
|
58
|
+
const wingRatio = defaultRadius * 5;
|
|
59
|
+
|
|
60
|
+
let {
|
|
61
|
+
data = [{}],
|
|
62
|
+
canvas,
|
|
63
|
+
shape = 'arrow',
|
|
64
|
+
anchor = 'middle',
|
|
65
|
+
r = defaultRadius,
|
|
66
|
+
...options
|
|
67
|
+
}: VectorMarkProps = $props();
|
|
68
|
+
|
|
69
|
+
const { getPlotState } = getContext<PlotContext>('svelteplot');
|
|
70
|
+
const plot = $derived(getPlotState());
|
|
71
|
+
|
|
72
|
+
const { getTestFacet } = getContext<FacetContext>('svelteplot/facet');
|
|
73
|
+
const testFacet = $derived(getTestFacet());
|
|
74
|
+
|
|
75
|
+
const shapeArrow: ShapeRenderer = {
|
|
76
|
+
draw(context: D3Path, l: number, r: number) {
|
|
77
|
+
const wing = (l * r) / wingRatio;
|
|
78
|
+
context.moveTo(0, 0);
|
|
79
|
+
context.lineTo(0, -l);
|
|
80
|
+
context.moveTo(-wing, wing - l);
|
|
81
|
+
context.lineTo(0, -l);
|
|
82
|
+
context.lineTo(wing, wing - l);
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
const shapeSpike: ShapeRenderer = {
|
|
87
|
+
draw(context: D3Path, l: number, r: number) {
|
|
88
|
+
context.moveTo(-r, 0);
|
|
89
|
+
context.lineTo(0, -l);
|
|
90
|
+
context.lineTo(r, 0);
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
const shapeArrowFilled: ShapeRenderer = {
|
|
95
|
+
draw(context: D3Path, l: number, r: number) {
|
|
96
|
+
// const wing = (l * r) / wingRatio;
|
|
97
|
+
const headLength = Math.max(3, l * 0.3);
|
|
98
|
+
const headSpike = headLength * 0.2;
|
|
99
|
+
const headWidth = Math.max(2, l * 0.3);
|
|
100
|
+
const tailWidth = Math.max(2, l * 0.3) * 0.3;
|
|
101
|
+
|
|
102
|
+
context.moveTo(0, 0);
|
|
103
|
+
|
|
104
|
+
context.lineTo(tailWidth * 0.5, -l + headLength - headSpike);
|
|
105
|
+
context.lineTo(headWidth * 0.5, -l + headLength);
|
|
106
|
+
context.lineTo(0, -l);
|
|
107
|
+
context.lineTo(-headWidth * 0.5, -l + headLength);
|
|
108
|
+
context.lineTo(-tailWidth * 0.5, -l + headLength - headSpike);
|
|
109
|
+
|
|
110
|
+
context.closePath();
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
const shapes = new Map([
|
|
115
|
+
['arrow', shapeArrow],
|
|
116
|
+
['arrow-filled', shapeArrowFilled],
|
|
117
|
+
['spike', shapeSpike]
|
|
118
|
+
]);
|
|
119
|
+
|
|
120
|
+
function isShapeObject(value: any): value is ShapeRenderer {
|
|
121
|
+
return value && typeof value.draw === 'function';
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
function maybeShape(shape: 'arrow' | 'spike' | 'arrow-filled' | ShapeRenderer) {
|
|
125
|
+
if (isShapeObject(shape)) return shape;
|
|
126
|
+
const value = shapes.get(`${shape}`.toLowerCase());
|
|
127
|
+
if (value) return value;
|
|
128
|
+
throw new Error(`invalid shape: ${shape}`);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function shapePath(
|
|
132
|
+
shape: 'arrow' | 'spike' | 'arrow-filled' | ShapeRenderer,
|
|
133
|
+
l: number,
|
|
134
|
+
r: number
|
|
135
|
+
) {
|
|
136
|
+
const context = path();
|
|
137
|
+
maybeShape(shape).draw(context, l, r);
|
|
138
|
+
return context.toString();
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
const args = $derived(
|
|
142
|
+
sort({
|
|
143
|
+
data: maybeData(data),
|
|
144
|
+
// sort by descending radius by default
|
|
145
|
+
...options
|
|
146
|
+
})
|
|
147
|
+
);
|
|
148
|
+
</script>
|
|
149
|
+
|
|
150
|
+
<Mark
|
|
151
|
+
type="vector"
|
|
152
|
+
required={['x', 'y']}
|
|
153
|
+
channels={[
|
|
154
|
+
'x',
|
|
155
|
+
'y',
|
|
156
|
+
'r',
|
|
157
|
+
'length',
|
|
158
|
+
'symbol',
|
|
159
|
+
'fill',
|
|
160
|
+
'opacity',
|
|
161
|
+
'stroke',
|
|
162
|
+
'fillOpacity',
|
|
163
|
+
'strokeOpacity'
|
|
164
|
+
]}
|
|
165
|
+
{...args}>
|
|
166
|
+
{#snippet children({ mark, scaledData, usedScales })}
|
|
167
|
+
<g class="vector" data-l={usedScales.length}>
|
|
168
|
+
{#if canvas}
|
|
169
|
+
<text x="30" y="30" style="color:red"
|
|
170
|
+
>implement canvas rendering for vector mark</text>
|
|
171
|
+
{:else}
|
|
172
|
+
{#each scaledData as d}
|
|
173
|
+
{@const r = resolveChannel('r', d.datum, { r: 3, ...args })}
|
|
174
|
+
{#if d.valid && isValid(r)}
|
|
175
|
+
{@const dx = +resolveProp(args.dx, d.datum, 0)}
|
|
176
|
+
{@const dy = +resolveProp(args.dx, d.datum, 0)}
|
|
177
|
+
{@const [style, styleClass] = resolveStyles(
|
|
178
|
+
plot,
|
|
179
|
+
d,
|
|
180
|
+
{
|
|
181
|
+
strokeWidth: 1.5,
|
|
182
|
+
strokeLinejoin: 'round',
|
|
183
|
+
strokeLinecap: 'round',
|
|
184
|
+
...args
|
|
185
|
+
},
|
|
186
|
+
shape === 'arrow-filled' ? 'fill' : 'stroke',
|
|
187
|
+
usedScales
|
|
188
|
+
)}
|
|
189
|
+
<path
|
|
190
|
+
d={shapePath(shape, d.length, r)}
|
|
191
|
+
transform="translate({d.x + dx}, {d.y + dy}) rotate({resolveProp(
|
|
192
|
+
args.rotate,
|
|
193
|
+
d.datum,
|
|
194
|
+
0
|
|
195
|
+
)}) {anchor === 'start'
|
|
196
|
+
? ''
|
|
197
|
+
: anchor === 'end'
|
|
198
|
+
? `translate(0, ${d.length})`
|
|
199
|
+
: `translate(0, ${d.length / 2})`}"
|
|
200
|
+
{style}
|
|
201
|
+
class={[styleClass]} />
|
|
202
|
+
{/if}
|
|
203
|
+
{/each}
|
|
204
|
+
{/if}
|
|
205
|
+
</g>
|
|
206
|
+
{/snippet}
|
|
207
|
+
</Mark>
|
|
208
|
+
|
|
209
|
+
<style>
|
|
210
|
+
path {
|
|
211
|
+
stroke-width: 1.5px;
|
|
212
|
+
}
|
|
213
|
+
</style>
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { DataRecord, BaseMarkProps, ConstantAccessor, ChannelAccessor } from '../types.js';
|
|
2
|
+
type D3Path = ReturnType<typeof import('d3-path').path>;
|
|
3
|
+
export type ShapeRenderer = {
|
|
4
|
+
draw(context: D3Path, l: number, r: number): void;
|
|
5
|
+
};
|
|
6
|
+
export type VectorMarkProps = BaseMarkProps & {
|
|
7
|
+
data: DataRecord[];
|
|
8
|
+
x: ChannelAccessor;
|
|
9
|
+
y: ChannelAccessor;
|
|
10
|
+
r?: number;
|
|
11
|
+
length?: ChannelAccessor;
|
|
12
|
+
rotate?: ChannelAccessor;
|
|
13
|
+
fill?: ChannelAccessor;
|
|
14
|
+
stroke?: ChannelAccessor;
|
|
15
|
+
/**
|
|
16
|
+
* Controls where the vector is anchored in relation to the x, y position.
|
|
17
|
+
* If set to 'start', the arrow will start at the x, y position. If set to
|
|
18
|
+
* 'middle', the arrow will be centered at the x, y position. If set to
|
|
19
|
+
* 'end', the arrow will end at the x, y position.
|
|
20
|
+
*/
|
|
21
|
+
anchor: 'start' | 'middle' | 'end';
|
|
22
|
+
shape?: 'arrow' | 'spike' | 'arrow-filled' | ShapeRenderer;
|
|
23
|
+
children?: Snippet;
|
|
24
|
+
dx?: ConstantAccessor<number>;
|
|
25
|
+
dy?: ConstantAccessor<number>;
|
|
26
|
+
canvas?: boolean;
|
|
27
|
+
};
|
|
28
|
+
import { type Snippet } from 'svelte';
|
|
29
|
+
declare const Vector: import("svelte").Component<VectorMarkProps, {}, "">;
|
|
30
|
+
type Vector = ReturnType<typeof Vector>;
|
|
31
|
+
export default Vector;
|