layerchart 0.54.0 → 0.55.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/dist/components/Arc.svelte +170 -144
- package/dist/components/Area.svelte +96 -67
- package/dist/components/Area.svelte.d.ts +1 -0
- package/dist/components/Axis.svelte +205 -155
- package/dist/components/Bar.svelte +72 -45
- package/dist/components/Bars.svelte +45 -34
- package/dist/components/Blur.svelte +5 -3
- package/dist/components/Bounds.svelte +37 -21
- package/dist/components/Brush.svelte +269 -112
- package/dist/components/Brush.svelte.d.ts +7 -0
- package/dist/components/Calendar.svelte +51 -38
- package/dist/components/Chart.svelte +295 -74
- package/dist/components/Chart.svelte.d.ts +17 -17
- package/dist/components/ChartClipPath.svelte +8 -5
- package/dist/components/ChartContext.svelte +243 -93
- package/dist/components/ChartContext.svelte.d.ts +15 -23
- package/dist/components/Circle.svelte +25 -16
- package/dist/components/CircleClipPath.svelte +16 -10
- package/dist/components/ClipPath.svelte +11 -7
- package/dist/components/ColorRamp.svelte +12 -10
- package/dist/components/ForceSimulation.svelte +185 -116
- package/dist/components/Frame.svelte +10 -6
- package/dist/components/GeoCircle.svelte +15 -9
- package/dist/components/GeoContext.svelte +109 -62
- package/dist/components/GeoEdgeFade.svelte +20 -14
- package/dist/components/GeoPath.svelte +107 -69
- package/dist/components/GeoPoint.svelte +32 -18
- package/dist/components/GeoSpline.svelte +30 -22
- package/dist/components/GeoTile.svelte +40 -30
- package/dist/components/GeoVisible.svelte +10 -7
- package/dist/components/Graticule.svelte +14 -8
- package/dist/components/Grid.svelte +75 -48
- package/dist/components/Group.svelte +43 -31
- package/dist/components/Highlight.svelte +284 -243
- package/dist/components/HitCanvas.svelte +75 -42
- package/dist/components/Hull.svelte +40 -20
- package/dist/components/Labels.svelte +81 -70
- package/dist/components/Legend.svelte +105 -74
- package/dist/components/Legend.svelte.d.ts +1 -1
- package/dist/components/Line.svelte +65 -19
- package/dist/components/Line.svelte.d.ts +13 -1
- package/dist/components/LinearGradient.svelte +21 -15
- package/dist/components/Link.svelte +94 -22
- package/dist/components/Link.svelte.d.ts +17 -1
- package/dist/components/Marker.svelte +81 -0
- package/dist/components/Marker.svelte.d.ts +28 -0
- package/dist/components/MonthPath.svelte +23 -16
- package/dist/components/MotionPath.svelte +34 -25
- package/dist/components/Pack.svelte +21 -14
- package/dist/components/Partition.svelte +35 -20
- package/dist/components/Pattern.svelte +8 -6
- package/dist/components/Pie.svelte +76 -57
- package/dist/components/Point.svelte +11 -7
- package/dist/components/Points.svelte +178 -143
- package/dist/components/RadialGradient.svelte +25 -18
- package/dist/components/Rect.svelte +33 -19
- package/dist/components/RectClipPath.svelte +16 -11
- package/dist/components/Rule.svelte +50 -42
- package/dist/components/Sankey.svelte +55 -30
- package/dist/components/Spline.svelte +167 -96
- package/dist/components/Spline.svelte.d.ts +15 -0
- package/dist/components/Text.svelte +137 -104
- package/dist/components/Threshold.svelte +18 -7
- package/dist/components/TileImage.svelte +56 -50
- package/dist/components/TransformContext.svelte +235 -135
- package/dist/components/TransformControls.svelte +57 -29
- package/dist/components/TransformControls.svelte.d.ts +1 -1
- package/dist/components/Tree.svelte +33 -23
- package/dist/components/Treemap.svelte +69 -41
- package/dist/components/Voronoi.svelte +55 -28
- package/dist/components/charts/AreaChart.svelte +138 -87
- package/dist/components/charts/AreaChart.svelte.d.ts +4 -4
- package/dist/components/charts/BarChart.svelte +179 -114
- package/dist/components/charts/BarChart.svelte.d.ts +4 -4
- package/dist/components/charts/LineChart.svelte +97 -53
- package/dist/components/charts/LineChart.svelte.d.ts +4 -4
- package/dist/components/charts/PieChart.svelte +104 -54
- package/dist/components/charts/PieChart.svelte.d.ts +3 -3
- package/dist/components/charts/ScatterChart.svelte +83 -48
- package/dist/components/charts/ScatterChart.svelte.d.ts +4 -4
- package/dist/components/layout/Canvas.svelte +63 -43
- package/dist/components/layout/Html.svelte +28 -18
- package/dist/components/layout/Svg.svelte +47 -32
- package/dist/components/tooltip/Tooltip.svelte +137 -91
- package/dist/components/tooltip/Tooltip.svelte.d.ts +1 -1
- package/dist/components/tooltip/TooltipContext.svelte +315 -249
- package/dist/components/tooltip/TooltipHeader.svelte +9 -3
- package/dist/components/tooltip/TooltipItem.svelte +17 -9
- package/dist/components/tooltip/TooltipList.svelte +2 -1
- package/dist/components/tooltip/TooltipSeparator.svelte +3 -2
- package/dist/docs/Blockquote.svelte +4 -3
- package/dist/docs/Code.svelte +15 -8
- package/dist/docs/CurveMenuField.svelte +17 -12
- package/dist/docs/GeoDebug.svelte +13 -9
- package/dist/docs/Header1.svelte +2 -1
- package/dist/docs/Json.svelte +6 -4
- package/dist/docs/Layout.svelte +6 -6
- package/dist/docs/PathDataMenuField.svelte +52 -44
- package/dist/docs/Preview.svelte +39 -33
- package/dist/docs/TilesetField.svelte +80 -62
- package/dist/docs/TransformDebug.svelte +8 -5
- package/dist/docs/ViewSourceButton.svelte +13 -9
- package/dist/stores/motionStore.d.ts +1 -1
- package/dist/utils/scales.d.ts +3 -3
- package/package.json +29 -30
|
@@ -1,206 +1,275 @@
|
|
|
1
|
-
<script>
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
let
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { createEventDispatcher } from 'svelte';
|
|
3
|
+
|
|
4
|
+
import { forceSimulation, type Force } from 'd3-force';
|
|
5
|
+
import { chartContext } from './ChartContext.svelte';
|
|
6
|
+
|
|
7
|
+
const { data } = chartContext();
|
|
8
|
+
|
|
9
|
+
const dispatch = createEventDispatcher<{
|
|
10
|
+
start: null;
|
|
11
|
+
tick: { alpha: number; alphaTarget: number };
|
|
12
|
+
change: null;
|
|
13
|
+
end: null;
|
|
14
|
+
}>();
|
|
15
|
+
|
|
16
|
+
// MARK: Public Props
|
|
17
|
+
|
|
18
|
+
type Forces = Record<string, Force<any, any>>;
|
|
19
|
+
export let forces: Forces;
|
|
20
|
+
|
|
21
|
+
export let alpha: number = 1;
|
|
22
|
+
export let alphaTarget: number = 0;
|
|
23
|
+
export let alphaDecay: number = 1 - Math.pow(0.001, 1 / 300);
|
|
24
|
+
export let alphaMin: number = 0.001;
|
|
25
|
+
|
|
26
|
+
export let velocityDecay = 0.4;
|
|
27
|
+
|
|
28
|
+
/** Stop simulation */
|
|
29
|
+
export let stopped = false;
|
|
30
|
+
|
|
31
|
+
let _static = false;
|
|
32
|
+
/** If true, will only update nodes after simulation has completed */
|
|
33
|
+
export { _static as static };
|
|
34
|
+
|
|
35
|
+
/** Clone data since simulation mutates original */
|
|
36
|
+
export const cloneData: boolean = false;
|
|
37
|
+
|
|
38
|
+
// MARK: Private Props
|
|
39
|
+
|
|
40
|
+
let nodes: any[] = [];
|
|
41
|
+
|
|
42
|
+
const simulation = forceSimulation().stop();
|
|
43
|
+
|
|
44
|
+
// d3.Simulation does not provide a `.forces()` getter, so we need to
|
|
45
|
+
// keep track of previous forces ourselves, for diffing against `forces`.
|
|
46
|
+
let previousForces: Forces = {};
|
|
47
|
+
|
|
48
|
+
let paused: boolean = true;
|
|
49
|
+
|
|
50
|
+
// MARK: Reactivity Effects
|
|
51
|
+
|
|
52
|
+
$: {
|
|
28
53
|
// Any time the `stopped` prop gets toggled we
|
|
29
54
|
// update the running state of the simulation:
|
|
55
|
+
|
|
30
56
|
if (stopped) {
|
|
31
|
-
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
runOrResumeSimulation();
|
|
57
|
+
pauseDynamicSimulation();
|
|
58
|
+
} else {
|
|
59
|
+
runOrResumeSimulation();
|
|
35
60
|
}
|
|
36
|
-
}
|
|
37
|
-
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
$: {
|
|
38
64
|
// Any time the `static` prop gets toggled we
|
|
39
65
|
// either attach or detach our internal event listeners:
|
|
40
66
|
if (_static) {
|
|
41
|
-
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
simulation.on('tick', onTick).on('end', onEnd);
|
|
67
|
+
simulation.on('tick', null).on('end', null);
|
|
68
|
+
} else {
|
|
69
|
+
simulation.on('tick', onTick).on('end', onEnd);
|
|
45
70
|
}
|
|
71
|
+
|
|
46
72
|
runOrResumeSimulation();
|
|
47
|
-
}
|
|
48
|
-
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
$: {
|
|
49
76
|
// Any time the `$data` store gets changed we
|
|
50
77
|
// pass them to the internal d3 simulation object:
|
|
51
|
-
pushNodesToSimulation($data);
|
|
78
|
+
pushNodesToSimulation($data as any[]);
|
|
52
79
|
runOrResumeSimulation();
|
|
53
|
-
}
|
|
54
|
-
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
$: {
|
|
55
83
|
// Any time the `forces` prop gets changed we
|
|
56
84
|
// pass them to the internal d3 simulation object:
|
|
57
85
|
pushForcesToSimulation(forces);
|
|
58
86
|
runOrResumeSimulation();
|
|
59
|
-
}
|
|
60
|
-
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
$: {
|
|
61
90
|
// Any time the `alpha` prop gets changed we
|
|
62
91
|
// pass it to the internal d3 simulation object:
|
|
63
92
|
pushAlphaToSimulation(alpha);
|
|
93
|
+
|
|
64
94
|
// Only resume the simulation as long as `alpha`
|
|
65
95
|
// is above the cut-off threshold of `alphaMin`,
|
|
66
96
|
// otherwise our simulation will never terminate:
|
|
67
97
|
if (simulation.alpha() >= simulation.alphaMin()) {
|
|
68
|
-
|
|
98
|
+
runOrResumeSimulation();
|
|
69
99
|
}
|
|
70
|
-
}
|
|
71
|
-
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
$: {
|
|
72
103
|
// Any time any of the the alpha props get changed we
|
|
73
104
|
// pass them all to the internal d3 simulation object
|
|
74
105
|
// (they are cheap, so passing them as a batch is fine!):
|
|
106
|
+
|
|
75
107
|
// We read `simulation.alpha()` instead of `alpha` here, so
|
|
76
108
|
// Svelte does not trigger this block on any change to `alpha`:
|
|
77
109
|
let alphaValue = simulation.alpha();
|
|
78
110
|
if (alphaTarget > alphaValue && alphaValue < alphaMin) {
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
111
|
+
// Lift `alpha` from below `alphaMin` in order to give the simulation
|
|
112
|
+
// a chance to get revived if an `alphaTarget > alpha` is provided:
|
|
113
|
+
alphaValue = alphaMin;
|
|
82
114
|
}
|
|
115
|
+
|
|
83
116
|
simulation
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
117
|
+
.alpha(alphaValue)
|
|
118
|
+
.alphaTarget(alphaTarget)
|
|
119
|
+
.alphaMin(alphaMin)
|
|
120
|
+
.alphaDecay(alphaDecay)
|
|
121
|
+
.velocityDecay(velocityDecay);
|
|
122
|
+
|
|
89
123
|
runOrResumeSimulation();
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// MARK: Push State
|
|
127
|
+
|
|
128
|
+
function pushAlphaToSimulation(alpha: number) {
|
|
93
129
|
simulation.alpha(alpha);
|
|
94
|
-
}
|
|
95
|
-
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function pushNodesToSimulation(nodes: any[]) {
|
|
96
133
|
simulation.nodes(cloneData ? structuredClone(nodes) : nodes);
|
|
97
|
-
}
|
|
98
|
-
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function pushForcesToSimulation(forces: Forces) {
|
|
99
137
|
// Evict obsolete forces:
|
|
100
138
|
Object.keys(previousForces).forEach((name) => {
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
139
|
+
if (!(name in forces)) {
|
|
140
|
+
simulation.force(name, null);
|
|
141
|
+
}
|
|
104
142
|
});
|
|
143
|
+
|
|
105
144
|
// Add new or overwrite existing forces:
|
|
106
145
|
Object.entries(forces).forEach(([name, force]) => {
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
146
|
+
if (!(name in previousForces) || force !== previousForces[name]) {
|
|
147
|
+
simulation.force(name, force);
|
|
148
|
+
}
|
|
110
149
|
});
|
|
150
|
+
|
|
111
151
|
previousForces = forces;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// MARK: Pull State
|
|
155
|
+
|
|
156
|
+
function pullNodesFromSimulation() {
|
|
115
157
|
nodes = simulation.nodes();
|
|
116
|
-
}
|
|
117
|
-
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
function pullAlphaFromSimulation() {
|
|
118
161
|
alpha = simulation.alpha();
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// MARK: Resume / Pause
|
|
165
|
+
|
|
166
|
+
function runOrResumeSimulation() {
|
|
122
167
|
if (_static) {
|
|
123
|
-
|
|
168
|
+
runStaticSimulationToCompletion();
|
|
169
|
+
} else {
|
|
170
|
+
resumeDynamicSimulation();
|
|
124
171
|
}
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
}
|
|
129
|
-
function runStaticSimulationToCompletion() {
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
function runStaticSimulationToCompletion() {
|
|
130
175
|
if (stopped) {
|
|
131
|
-
|
|
132
|
-
|
|
176
|
+
// If a simulation is marked as stopped, then it should not get started.
|
|
177
|
+
return;
|
|
133
178
|
}
|
|
179
|
+
|
|
134
180
|
if (!_static) {
|
|
135
|
-
|
|
136
|
-
|
|
181
|
+
// Only static simulations are run to completion.
|
|
182
|
+
return;
|
|
137
183
|
}
|
|
184
|
+
|
|
138
185
|
if (!paused) {
|
|
139
|
-
|
|
140
|
-
|
|
186
|
+
// Pause any possibly still running dynamic simulation:
|
|
187
|
+
pauseDynamicSimulation();
|
|
141
188
|
}
|
|
142
|
-
|
|
189
|
+
|
|
190
|
+
const ticks = Math.ceil(
|
|
191
|
+
Math.log(simulation.alphaMin()) / Math.log(1 - simulation.alphaDecay())
|
|
192
|
+
);
|
|
193
|
+
|
|
143
194
|
pushAlphaToSimulation(1.0);
|
|
195
|
+
|
|
144
196
|
onStart();
|
|
197
|
+
|
|
145
198
|
for (let i = 0; i < ticks; ++i) {
|
|
146
|
-
|
|
199
|
+
simulation.tick();
|
|
147
200
|
}
|
|
201
|
+
|
|
148
202
|
pullNodesFromSimulation();
|
|
149
203
|
pullAlphaFromSimulation();
|
|
204
|
+
|
|
150
205
|
onEnd();
|
|
151
|
-
}
|
|
152
|
-
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
function resumeDynamicSimulation() {
|
|
153
209
|
if (!paused) {
|
|
154
|
-
|
|
155
|
-
|
|
210
|
+
// No need to restart an already running simulation.
|
|
211
|
+
return;
|
|
156
212
|
}
|
|
213
|
+
|
|
157
214
|
if (stopped) {
|
|
158
|
-
|
|
159
|
-
|
|
215
|
+
// If a simulation is marked as stopped, then it should not get resumed.
|
|
216
|
+
return;
|
|
160
217
|
}
|
|
218
|
+
|
|
161
219
|
if (_static) {
|
|
162
|
-
|
|
163
|
-
|
|
220
|
+
// Only dynamic simulations can be resumed.
|
|
221
|
+
return;
|
|
164
222
|
}
|
|
223
|
+
|
|
165
224
|
onStart();
|
|
166
225
|
simulation.restart();
|
|
226
|
+
|
|
167
227
|
// No need to call `onEnd();` for dynamic simulations
|
|
168
228
|
// as the simulation itself takes care of firing `on:end`,
|
|
169
229
|
// which then gets calls `onEnd();` for us.
|
|
170
|
-
}
|
|
171
|
-
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
function pauseDynamicSimulation() {
|
|
172
233
|
if (paused) {
|
|
173
|
-
|
|
174
|
-
|
|
234
|
+
// No need to pause an already paused simulation.
|
|
235
|
+
return;
|
|
175
236
|
}
|
|
237
|
+
|
|
176
238
|
simulation.stop();
|
|
177
239
|
onEnd();
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// MARK: Event Listeners
|
|
243
|
+
|
|
244
|
+
function onStart() {
|
|
181
245
|
if (!paused) {
|
|
182
|
-
|
|
183
|
-
|
|
246
|
+
// Avoid double-emissions of `start` event due to race conditions.
|
|
247
|
+
return;
|
|
184
248
|
}
|
|
249
|
+
|
|
185
250
|
paused = false;
|
|
186
251
|
dispatch('start');
|
|
187
|
-
}
|
|
188
|
-
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
function onTick() {
|
|
189
255
|
pullNodesFromSimulation();
|
|
190
256
|
pullAlphaFromSimulation();
|
|
257
|
+
|
|
191
258
|
dispatch('tick', {
|
|
192
|
-
|
|
193
|
-
|
|
259
|
+
alpha,
|
|
260
|
+
alphaTarget,
|
|
194
261
|
});
|
|
195
|
-
}
|
|
196
|
-
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
function onEnd() {
|
|
197
265
|
if (paused) {
|
|
198
|
-
|
|
199
|
-
|
|
266
|
+
// Avoid double-emissions of `end` event due to race conditions.
|
|
267
|
+
return;
|
|
200
268
|
}
|
|
269
|
+
|
|
201
270
|
paused = true;
|
|
202
271
|
dispatch('end');
|
|
203
|
-
}
|
|
272
|
+
}
|
|
204
273
|
</script>
|
|
205
274
|
|
|
206
275
|
<slot {nodes} {simulation} />
|
|
@@ -1,9 +1,13 @@
|
|
|
1
|
-
<script>
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { chartContext } from './ChartContext.svelte';
|
|
3
|
+
|
|
4
|
+
const { width, height, padding } = chartContext();
|
|
5
|
+
|
|
6
|
+
/** Include padding area */
|
|
7
|
+
export let full = false;
|
|
8
|
+
|
|
9
|
+
/** Access underlying `<rect>` element */
|
|
10
|
+
export let rectEl: SVGRectElement | undefined = undefined;
|
|
7
11
|
</script>
|
|
8
12
|
|
|
9
13
|
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
|
@@ -1,12 +1,18 @@
|
|
|
1
|
-
<script>
|
|
2
|
-
import
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { geoCircle } from 'd3-geo';
|
|
3
|
+
|
|
4
|
+
import GeoPath from './GeoPath.svelte';
|
|
5
|
+
|
|
6
|
+
/** Radius in degrees. Default: 90 */
|
|
7
|
+
export let radius = 90;
|
|
8
|
+
|
|
9
|
+
/** Center point of circle in degree ([longitude, latitude]). Default [0, 0] */
|
|
10
|
+
export let center: [number, number] = [0, 0];
|
|
11
|
+
|
|
12
|
+
/** sets the circle precision to the specified angle in degrees */
|
|
13
|
+
export let precision = 6;
|
|
14
|
+
|
|
15
|
+
$: geojson = geoCircle().radius(radius).center(center).precision(precision)();
|
|
10
16
|
</script>
|
|
11
17
|
|
|
12
18
|
<GeoPath {geojson} {...$$restProps} on:pointermove on:pointerleave on:click />
|
|
@@ -1,88 +1,135 @@
|
|
|
1
|
-
<script context="module">
|
|
2
|
-
import {
|
|
3
|
-
import {} from '
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
1
|
+
<script lang="ts" context="module">
|
|
2
|
+
import { getContext, setContext } from 'svelte';
|
|
3
|
+
import { writable, type Writable } from 'svelte/store';
|
|
4
|
+
import {
|
|
5
|
+
type GeoIdentityTransform,
|
|
6
|
+
type GeoPermissibleObjects,
|
|
7
|
+
type GeoProjection,
|
|
8
|
+
} from 'd3-geo';
|
|
9
|
+
|
|
10
|
+
import { chartContext } from './ChartContext.svelte';
|
|
11
|
+
import { transformContext } from './TransformContext.svelte';
|
|
12
|
+
|
|
13
|
+
export const geoContextKey = Symbol();
|
|
14
|
+
|
|
15
|
+
export type GeoContext = Writable<GeoProjection /* | GeoIdentityTransform*/>;
|
|
16
|
+
|
|
17
|
+
export function geoContext() {
|
|
18
|
+
return getContext<GeoContext>(geoContextKey);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function setGeoContext(geo: GeoContext) {
|
|
11
22
|
setContext(geoContextKey, geo);
|
|
12
|
-
}
|
|
23
|
+
}
|
|
13
24
|
</script>
|
|
14
25
|
|
|
15
|
-
<script
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
export let
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
export let
|
|
25
|
-
|
|
26
|
-
export let
|
|
27
|
-
|
|
28
|
-
export let
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
26
|
+
<script lang="ts">
|
|
27
|
+
const { width, height } = chartContext();
|
|
28
|
+
|
|
29
|
+
/** @type {Function} projection - A d3 projection function. Pass this in as an uncalled function, e.g. `projection={geoAlbersUsa}`. */
|
|
30
|
+
export let projection: (() => GeoProjection) /* | GeoIdentityTransform*/ | undefined = undefined;
|
|
31
|
+
|
|
32
|
+
export let fitGeojson: GeoPermissibleObjects | undefined = undefined;
|
|
33
|
+
|
|
34
|
+
/** By default, the map fills to fit the $width and $height. If instead you want a fixed-aspect ratio, like for a server-side rendered map, set that here. */
|
|
35
|
+
export let fixedAspectRatio: number | undefined = undefined;
|
|
36
|
+
|
|
37
|
+
export let clipAngle: number | undefined = undefined;
|
|
38
|
+
export let clipExtent: [[number, number], [number, number]] | undefined = undefined;
|
|
39
|
+
export let rotate:
|
|
40
|
+
| {
|
|
41
|
+
/** Lambda (Center Meridian) */
|
|
42
|
+
yaw: number;
|
|
43
|
+
/** Phi */
|
|
44
|
+
pitch: number;
|
|
45
|
+
/** Gamma */
|
|
46
|
+
roll: number;
|
|
47
|
+
}
|
|
48
|
+
| undefined = undefined;
|
|
49
|
+
export let scale: number | undefined = undefined;
|
|
50
|
+
export let translate: [number, number] | undefined = undefined;
|
|
51
|
+
export let center: [number, number] | undefined = undefined;
|
|
52
|
+
|
|
53
|
+
/** Apply TransformContext to the selected properties. Typically `translate` or `rotate` are mutually selected */
|
|
54
|
+
export let applyTransform: ('scale' | 'translate' | 'rotate')[] = [];
|
|
55
|
+
|
|
56
|
+
export let reflectX: boolean | undefined = undefined;
|
|
57
|
+
export let reflectY: boolean | undefined = undefined;
|
|
58
|
+
|
|
59
|
+
/** Exposed to allow binding in Chart */
|
|
60
|
+
export let geo = writable(projection?.());
|
|
61
|
+
setGeoContext(geo);
|
|
62
|
+
|
|
63
|
+
const { scale: transformScale, translate: transformTranslate } = transformContext();
|
|
64
|
+
|
|
65
|
+
$: fitSizeRange = (fixedAspectRatio ? [100, 100 / fixedAspectRatio] : [$width, $height]) as [
|
|
66
|
+
number,
|
|
67
|
+
number,
|
|
68
|
+
];
|
|
69
|
+
|
|
70
|
+
$: if (projection) {
|
|
37
71
|
const _projection = projection();
|
|
72
|
+
|
|
38
73
|
if (fitGeojson && 'fitSize' in _projection) {
|
|
39
|
-
|
|
74
|
+
_projection.fitSize(fitSizeRange, fitGeojson);
|
|
40
75
|
}
|
|
76
|
+
|
|
41
77
|
if ('scale' in _projection) {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
78
|
+
if (scale) {
|
|
79
|
+
_projection.scale(scale);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if (applyTransform.includes('scale')) {
|
|
83
|
+
_projection.scale($transformScale);
|
|
84
|
+
}
|
|
48
85
|
}
|
|
86
|
+
|
|
49
87
|
if ('rotate' in _projection) {
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
88
|
+
if (rotate) {
|
|
89
|
+
_projection.rotate([rotate.yaw, rotate.pitch, rotate.roll]);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
if (applyTransform.includes('rotate')) {
|
|
93
|
+
_projection.rotate([
|
|
94
|
+
$transformTranslate.x, // yaw
|
|
95
|
+
$transformTranslate.y, // pitch
|
|
96
|
+
// TODO: `roll` from `transformContext`?
|
|
97
|
+
]);
|
|
98
|
+
}
|
|
60
99
|
}
|
|
100
|
+
|
|
61
101
|
if ('translate' in _projection) {
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
102
|
+
if (translate) {
|
|
103
|
+
_projection.translate(translate);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (applyTransform.includes('translate')) {
|
|
107
|
+
_projection.translate([$transformTranslate.x, $transformTranslate.y]);
|
|
108
|
+
}
|
|
68
109
|
}
|
|
110
|
+
|
|
69
111
|
if (center && 'center' in _projection) {
|
|
70
|
-
|
|
112
|
+
_projection.center(center);
|
|
71
113
|
}
|
|
114
|
+
|
|
72
115
|
if (reflectX) {
|
|
73
|
-
|
|
116
|
+
_projection.reflectX(reflectX);
|
|
74
117
|
}
|
|
118
|
+
|
|
75
119
|
if (reflectY) {
|
|
76
|
-
|
|
120
|
+
_projection.reflectY(reflectY);
|
|
77
121
|
}
|
|
122
|
+
|
|
78
123
|
if (clipAngle && 'clipAngle' in _projection) {
|
|
79
|
-
|
|
124
|
+
_projection.clipAngle(clipAngle);
|
|
80
125
|
}
|
|
126
|
+
|
|
81
127
|
if (clipExtent && 'clipExtent' in _projection) {
|
|
82
|
-
|
|
128
|
+
_projection.clipExtent(clipExtent);
|
|
83
129
|
}
|
|
130
|
+
|
|
84
131
|
geo.set(_projection);
|
|
85
|
-
}
|
|
132
|
+
}
|
|
86
133
|
</script>
|
|
87
134
|
|
|
88
135
|
<slot projection={$geo} />
|