@dxos/react-ui-geo 0.8.4-staging.ac66bdf99f → 0.9.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/LICENSE +102 -5
- package/data/countries-10m.ts +12 -0
- package/data/countries-110m.ts +4 -10579
- package/data/countries-50m.ts +12 -0
- package/dist/lib/browser/chunk-SC2FBYFU.mjs +17 -0
- package/dist/lib/browser/chunk-SC2FBYFU.mjs.map +7 -0
- package/dist/lib/browser/countries-10m-CWWDOKH7.mjs +6 -0
- package/dist/lib/browser/countries-10m-CWWDOKH7.mjs.map +7 -0
- package/dist/lib/browser/countries-110m-72QBAA5E.mjs +6 -0
- package/dist/lib/browser/countries-110m-72QBAA5E.mjs.map +7 -0
- package/dist/lib/browser/countries-50m-H7SL7KVF.mjs +6 -0
- package/dist/lib/browser/countries-50m-H7SL7KVF.mjs.map +7 -0
- package/dist/lib/browser/data.mjs +1 -1
- package/dist/lib/browser/index.mjs +774 -223
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/translations.mjs +19 -0
- package/dist/lib/browser/translations.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-VZENBYLJ.mjs +19 -0
- package/dist/lib/node-esm/chunk-VZENBYLJ.mjs.map +7 -0
- package/dist/lib/node-esm/countries-10m-DJZV66KG.mjs +8 -0
- package/dist/lib/node-esm/countries-10m-DJZV66KG.mjs.map +7 -0
- package/dist/lib/node-esm/countries-110m-H3WY6K4Q.mjs +8 -0
- package/dist/lib/node-esm/countries-110m-H3WY6K4Q.mjs.map +7 -0
- package/dist/lib/node-esm/countries-50m-ZY7Z3IWD.mjs +8 -0
- package/dist/lib/node-esm/countries-50m-ZY7Z3IWD.mjs.map +7 -0
- package/dist/lib/node-esm/data.mjs +1 -1
- package/dist/lib/node-esm/index.mjs +774 -223
- package/dist/lib/node-esm/index.mjs.map +4 -4
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/lib/node-esm/translations.mjs +21 -0
- package/dist/lib/node-esm/translations.mjs.map +7 -0
- package/dist/types/data/airports.d.ts +4 -4
- package/dist/types/data/airports.d.ts.map +1 -1
- package/dist/types/data/cities.d.ts.map +1 -1
- package/dist/types/data/countries-10m.d.ts +8 -0
- package/dist/types/data/countries-10m.d.ts.map +1 -0
- package/dist/types/data/countries-110m.d.ts +2 -30
- package/dist/types/data/countries-110m.d.ts.map +1 -1
- package/dist/types/data/countries-50m.d.ts +8 -0
- package/dist/types/data/countries-50m.d.ts.map +1 -0
- package/dist/types/data/countries-dots-3.d.ts.map +1 -1
- package/dist/types/data/countries-dots-4.d.ts.map +1 -1
- package/dist/types/src/components/Globe/Globe.d.ts +18 -10
- package/dist/types/src/components/Globe/Globe.d.ts.map +1 -1
- package/dist/types/src/components/Globe/Globe.stories.d.ts +16 -8
- package/dist/types/src/components/Globe/Globe.stories.d.ts.map +1 -1
- package/dist/types/src/components/Map/Map.d.ts +49 -13
- package/dist/types/src/components/Map/Map.d.ts.map +1 -1
- package/dist/types/src/components/Map/Map.stories.d.ts +9 -5
- package/dist/types/src/components/Map/Map.stories.d.ts.map +1 -1
- package/dist/types/src/components/Toolbar/Controls.d.ts.map +1 -1
- package/dist/types/src/data.d.ts +9 -1
- package/dist/types/src/data.d.ts.map +1 -1
- package/dist/types/src/hooks/context.d.ts +37 -0
- package/dist/types/src/hooks/context.d.ts.map +1 -1
- package/dist/types/src/hooks/index.d.ts +3 -0
- package/dist/types/src/hooks/index.d.ts.map +1 -1
- package/dist/types/src/hooks/useDrag.d.ts +22 -2
- package/dist/types/src/hooks/useDrag.d.ts.map +1 -1
- package/dist/types/src/hooks/useGlobeZoomHandler.d.ts +3 -2
- package/dist/types/src/hooks/useGlobeZoomHandler.d.ts.map +1 -1
- package/dist/types/src/hooks/useMapZoomHandler.d.ts +1 -1
- package/dist/types/src/hooks/useMapZoomHandler.d.ts.map +1 -1
- package/dist/types/src/hooks/useSimplifiedTopology.d.ts +32 -0
- package/dist/types/src/hooks/useSimplifiedTopology.d.ts.map +1 -0
- package/dist/types/src/hooks/useSpinner.d.ts +1 -1
- package/dist/types/src/hooks/useSpinner.d.ts.map +1 -1
- package/dist/types/src/hooks/useTopology.d.ts +26 -0
- package/dist/types/src/hooks/useTopology.d.ts.map +1 -0
- package/dist/types/src/hooks/useTour.d.ts +3 -2
- package/dist/types/src/hooks/useTour.d.ts.map +1 -1
- package/dist/types/src/hooks/useWheel.d.ts +24 -0
- package/dist/types/src/hooks/useWheel.d.ts.map +1 -0
- package/dist/types/src/index.d.ts +0 -2
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/translations.d.ts +4 -4
- package/dist/types/src/translations.d.ts.map +1 -1
- package/dist/types/src/util/animation.d.ts +16 -0
- package/dist/types/src/util/animation.d.ts.map +1 -0
- package/dist/types/src/util/debug.d.ts.map +1 -1
- package/dist/types/src/util/index.d.ts +2 -0
- package/dist/types/src/util/index.d.ts.map +1 -1
- package/dist/types/src/util/inertia.d.ts.map +1 -1
- package/dist/types/src/util/path.d.ts.map +1 -1
- package/dist/types/src/util/render.d.ts +25 -1
- package/dist/types/src/util/render.d.ts.map +1 -1
- package/dist/types/src/util/styles.d.ts +4 -0
- package/dist/types/src/util/styles.d.ts.map +1 -0
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +26 -24
- package/src/components/Globe/Globe.stories.tsx +135 -58
- package/src/components/Globe/Globe.tsx +237 -120
- package/src/components/Map/Map.stories.tsx +58 -12
- package/src/components/Map/Map.tsx +293 -91
- package/src/components/Toolbar/Controls.tsx +1 -1
- package/src/data.ts +19 -2
- package/src/hooks/context.tsx +44 -0
- package/src/hooks/index.ts +3 -0
- package/src/hooks/useDrag.ts +33 -5
- package/src/hooks/useGlobeZoomHandler.ts +2 -1
- package/src/hooks/useSimplifiedTopology.ts +81 -0
- package/src/hooks/useSpinner.ts +1 -1
- package/src/hooks/useTopology.ts +95 -0
- package/src/hooks/useTour.ts +70 -81
- package/src/hooks/useWheel.ts +83 -0
- package/src/index.ts +0 -2
- package/src/util/animation.ts +35 -0
- package/src/util/index.ts +2 -0
- package/src/util/inertia.ts +87 -4
- package/src/util/render.ts +105 -16
- package/src/util/styles.ts +62 -0
- package/dist/lib/browser/chunk-GMWLKTLN.mjs +0 -9
- package/dist/lib/browser/chunk-GMWLKTLN.mjs.map +0 -7
- package/dist/lib/browser/countries-110m-ZM3ZIEFS.mjs +0 -37859
- package/dist/lib/browser/countries-110m-ZM3ZIEFS.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-JODBF4CC.mjs +0 -11
- package/dist/lib/node-esm/chunk-JODBF4CC.mjs.map +0 -7
- package/dist/lib/node-esm/countries-110m-3SFASWVD.mjs +0 -37861
- package/dist/lib/node-esm/countries-110m-3SFASWVD.mjs.map +0 -7
package/src/util/inertia.ts
CHANGED
|
@@ -28,14 +28,20 @@ export const geoInertiaDrag = (target, render, projection, options) => {
|
|
|
28
28
|
}
|
|
29
29
|
target = select(target);
|
|
30
30
|
|
|
31
|
-
//
|
|
32
|
-
|
|
31
|
+
// `linear` (default) constrains rotation so that mouse Δx maps to lambda
|
|
32
|
+
// (polar spin) and Δy maps to phi (tilt); gamma is held at 0.
|
|
33
|
+
// `versor` lets the dragged point follow the cursor exactly, at the cost of
|
|
34
|
+
// inducing some roll. In linear mode `lockTilt` keeps phi pinned but still
|
|
35
|
+
// allows lambda from Δx.
|
|
36
|
+
const linear = (options.mode ?? 'linear') === 'linear';
|
|
37
|
+
const axis = restrictAxis(options.lockTilt ? [true, false, false] : [true, true, true]);
|
|
38
|
+
const sharedHandlers = {
|
|
33
39
|
projection,
|
|
34
40
|
render: (rotation) => {
|
|
35
41
|
projection.rotate(rotation);
|
|
36
42
|
render && render();
|
|
37
43
|
},
|
|
38
|
-
axis
|
|
44
|
+
axis,
|
|
39
45
|
start: options.start,
|
|
40
46
|
move: options.move,
|
|
41
47
|
end: options.end,
|
|
@@ -43,7 +49,16 @@ export const geoInertiaDrag = (target, render, projection, options) => {
|
|
|
43
49
|
finish: options.finish,
|
|
44
50
|
time: options.time,
|
|
45
51
|
hold: options.hold,
|
|
46
|
-
}
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
// Complete params: (projection, render, startDrag, dragging, endDrag).
|
|
55
|
+
const inertia = linear
|
|
56
|
+
? geoInertiaDragLinearHelper({
|
|
57
|
+
...sharedHandlers,
|
|
58
|
+
sensitivity: options.sensitivity,
|
|
59
|
+
getZoom: options.getZoom,
|
|
60
|
+
})
|
|
61
|
+
: geoInertiaDragHelper(sharedHandlers);
|
|
47
62
|
|
|
48
63
|
target.call(drag().on('start', inertia.start).on('drag', inertia.move).on('end', inertia.end));
|
|
49
64
|
return inertia;
|
|
@@ -112,6 +127,74 @@ const geoInertiaDragHelper = (opt) => {
|
|
|
112
127
|
return inertia;
|
|
113
128
|
};
|
|
114
129
|
|
|
130
|
+
/**
|
|
131
|
+
* Linear pixel-to-Euler drag: Δx → lambda, Δy → phi, gamma fixed at 0.
|
|
132
|
+
* Inertia spin-down reuses the same shared decay curve as the versor path.
|
|
133
|
+
*/
|
|
134
|
+
const DEFAULT_LINEAR_SENSITIVITY = 0.25;
|
|
135
|
+
|
|
136
|
+
const geoInertiaDragLinearHelper = (opt) => {
|
|
137
|
+
const projection = opt.projection;
|
|
138
|
+
const sensitivity = opt.sensitivity ?? DEFAULT_LINEAR_SENSITIVITY;
|
|
139
|
+
// Scale degrees-per-pixel by 1/zoom so the drag feels consistent at any zoom
|
|
140
|
+
// level (mirrors useWheel — a more zoomed-in globe needs smaller angular
|
|
141
|
+
// rotation per pixel of cursor travel). Clamped to a floor so very small
|
|
142
|
+
// zoom values don't blow up the gain.
|
|
143
|
+
const gain = () => sensitivity / Math.max(opt.getZoom?.() ?? 1, 0.1);
|
|
144
|
+
|
|
145
|
+
let r0; // Projection rotation as Euler angles at start of drag.
|
|
146
|
+
let p0; // Pointer pixel position at start of drag.
|
|
147
|
+
let kStart; // Gain captured at start of drag (held for the gesture + inertia).
|
|
148
|
+
let rEnd; // Projection rotation at end of drag.
|
|
149
|
+
let vEnd; // Pointer velocity (px/s) at end of drag.
|
|
150
|
+
|
|
151
|
+
const inertia = inertiaHelper({
|
|
152
|
+
axis: opt.axis,
|
|
153
|
+
|
|
154
|
+
start: () => {
|
|
155
|
+
r0 = projection.rotate();
|
|
156
|
+
p0 = [inertia.position[0], inertia.position[1]];
|
|
157
|
+
// Lock the gain at gesture start so a zoom change mid-gesture doesn't
|
|
158
|
+
// teleport the globe; inertia continues at the same gain.
|
|
159
|
+
kStart = gain();
|
|
160
|
+
opt.start && opt.start();
|
|
161
|
+
},
|
|
162
|
+
|
|
163
|
+
move: () => {
|
|
164
|
+
const dx = inertia.position[0] - p0[0];
|
|
165
|
+
const dy = inertia.position[1] - p0[1];
|
|
166
|
+
// Screen y grows downward; negate so dragging down rotates the globe to
|
|
167
|
+
// match the cursor (matches the feel of the versor-based path).
|
|
168
|
+
const r1 = [r0[0] + dx * kStart, r0[1] - dy * kStart, 0];
|
|
169
|
+
const r2 = opt.axis(r0, r1);
|
|
170
|
+
opt.render(r2);
|
|
171
|
+
opt.move && opt.move();
|
|
172
|
+
},
|
|
173
|
+
|
|
174
|
+
end: () => {
|
|
175
|
+
rEnd = projection.rotate();
|
|
176
|
+
vEnd = [inertia.velocity[0], inertia.velocity[1]];
|
|
177
|
+
opt.end && opt.end();
|
|
178
|
+
},
|
|
179
|
+
|
|
180
|
+
stop: opt.stop,
|
|
181
|
+
|
|
182
|
+
finish: opt.finish,
|
|
183
|
+
|
|
184
|
+
render: (t) => {
|
|
185
|
+
// t goes 0→1 along the decay curve; at t=1 we've added ~1s of velocity.
|
|
186
|
+
// dy sign flipped to match the move handler.
|
|
187
|
+
const r1 = [rEnd[0] + vEnd[0] * kStart * t, rEnd[1] - vEnd[1] * kStart * t, 0];
|
|
188
|
+
const r2 = opt.axis(rEnd, r1);
|
|
189
|
+
opt.render && opt.render(r2);
|
|
190
|
+
},
|
|
191
|
+
|
|
192
|
+
time: opt.time,
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
return inertia;
|
|
196
|
+
};
|
|
197
|
+
|
|
115
198
|
function inertiaHelper(opt) {
|
|
116
199
|
const A = opt.time || 5_000; // Reference time in ms.
|
|
117
200
|
const limit = 1.0001;
|
package/src/util/render.ts
CHANGED
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
// Copyright 2020 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import { type GeoPath, type GeoPermissibleObjects, geoGraticule } from 'd3';
|
|
5
|
+
import { type GeoPath, type GeoPermissibleObjects, geoBounds, geoCentroid, geoDistance, geoGraticule } from 'd3';
|
|
6
|
+
import { type Feature, type Geometry } from 'geojson';
|
|
6
7
|
import { feature, mesh } from 'topojson-client';
|
|
7
8
|
import { type Topology } from 'topojson-specification';
|
|
8
9
|
|
|
@@ -30,9 +31,57 @@ export type Features = {
|
|
|
30
31
|
lines?: { source: LatLngLiteral; target: LatLngLiteral }[];
|
|
31
32
|
};
|
|
32
33
|
|
|
34
|
+
/**
|
|
35
|
+
* Per-feature bounding circle used for view-frustum culling on an
|
|
36
|
+
* orthographic globe. `centroid` is in lon/lat degrees and `radius` is the
|
|
37
|
+
* angular distance (degrees) from the centroid to the farthest sampled
|
|
38
|
+
* vertex of the feature.
|
|
39
|
+
*/
|
|
40
|
+
export type FeatureBounds = {
|
|
41
|
+
geometry: Geometry;
|
|
42
|
+
centroid: [number, number];
|
|
43
|
+
radius: number;
|
|
44
|
+
};
|
|
45
|
+
|
|
33
46
|
export type Layer = {
|
|
34
47
|
styles: Styles;
|
|
35
48
|
path: GeoPermissibleObjects;
|
|
49
|
+
/**
|
|
50
|
+
* If present, this layer is treated as a `GeometryCollection` whose
|
|
51
|
+
* member geometries are filtered per-frame by `viewCenter` against each
|
|
52
|
+
* member's `FeatureBounds`. `path` becomes the *unculled* fallback used
|
|
53
|
+
* when no `viewCenter` is supplied (e.g. non-orthographic projections).
|
|
54
|
+
*/
|
|
55
|
+
cullable?: FeatureBounds[];
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
const RAD_TO_DEG = 180 / Math.PI;
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Compute a spherical bounding circle for a GeoJSON feature. We sample the
|
|
62
|
+
* geoBounds corners (cheap, sufficient for typical country shapes); for
|
|
63
|
+
* features crossing the antimeridian d3.geoBounds returns west > east, which
|
|
64
|
+
* geoDistance handles correctly when called on the actual centroid.
|
|
65
|
+
*/
|
|
66
|
+
const computeBounds = (geometry: Geometry): FeatureBounds => {
|
|
67
|
+
const feat: Feature = { type: 'Feature', geometry, properties: {} };
|
|
68
|
+
const centroid = geoCentroid(feat) as [number, number];
|
|
69
|
+
const [[w, s], [e, n]] = geoBounds(feat);
|
|
70
|
+
// Sample the four bbox corners; widest is the bounding radius.
|
|
71
|
+
const corners: Array<[number, number]> = [
|
|
72
|
+
[w, s],
|
|
73
|
+
[w, n],
|
|
74
|
+
[e, s],
|
|
75
|
+
[e, n],
|
|
76
|
+
];
|
|
77
|
+
let radius = 0;
|
|
78
|
+
for (const corner of corners) {
|
|
79
|
+
const d = geoDistance(centroid, corner) * RAD_TO_DEG;
|
|
80
|
+
if (d > radius) {
|
|
81
|
+
radius = d;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return { geometry, centroid, radius };
|
|
36
85
|
};
|
|
37
86
|
|
|
38
87
|
/**
|
|
@@ -62,11 +111,25 @@ export const createLayers = (topology: Topology, features: Features, styles: Sty
|
|
|
62
111
|
//
|
|
63
112
|
|
|
64
113
|
if (topology) {
|
|
65
|
-
if (
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
114
|
+
if (styles.land) {
|
|
115
|
+
// Prefer the `countries` GeometryCollection over the merged `land`
|
|
116
|
+
// multipolygon so each country can be culled independently. Visually
|
|
117
|
+
// identical (countries collectively tile the land surface).
|
|
118
|
+
if (topology.objects.countries) {
|
|
119
|
+
const fc = feature(topology, topology.objects.countries) as any;
|
|
120
|
+
const memberGeoms: Geometry[] = fc.features.map((f: Feature) => f.geometry);
|
|
121
|
+
const bounds = memberGeoms.map(computeBounds);
|
|
122
|
+
layers.push({
|
|
123
|
+
styles: styles.land,
|
|
124
|
+
path: { type: 'GeometryCollection', geometries: memberGeoms } as any,
|
|
125
|
+
cullable: bounds,
|
|
126
|
+
});
|
|
127
|
+
} else if (topology.objects.land) {
|
|
128
|
+
layers.push({
|
|
129
|
+
styles: styles.land,
|
|
130
|
+
path: feature(topology, topology.objects.land),
|
|
131
|
+
});
|
|
132
|
+
}
|
|
70
133
|
}
|
|
71
134
|
|
|
72
135
|
if (topology.objects.countries && styles.border) {
|
|
@@ -91,22 +154,24 @@ export const createLayers = (topology: Topology, features: Features, styles: Sty
|
|
|
91
154
|
if (features) {
|
|
92
155
|
const { points, lines } = features;
|
|
93
156
|
|
|
94
|
-
|
|
157
|
+
// Lines first so points (drawn after) sit on top — the route nodes should
|
|
158
|
+
// never be occluded by an arc that passes through them.
|
|
159
|
+
if (lines && styles.line) {
|
|
95
160
|
layers.push({
|
|
96
|
-
styles: styles.
|
|
161
|
+
styles: styles.line,
|
|
97
162
|
path: {
|
|
98
163
|
type: 'GeometryCollection',
|
|
99
|
-
geometries:
|
|
164
|
+
geometries: lines.map(({ source, target }) => geoLine(source, target)),
|
|
100
165
|
},
|
|
101
166
|
});
|
|
102
167
|
}
|
|
103
168
|
|
|
104
|
-
if (
|
|
169
|
+
if (points && styles.point) {
|
|
105
170
|
layers.push({
|
|
106
|
-
styles: styles.
|
|
171
|
+
styles: styles.point,
|
|
107
172
|
path: {
|
|
108
173
|
type: 'GeometryCollection',
|
|
109
|
-
geometries:
|
|
174
|
+
geometries: points.map((point) => geoPoint(point)),
|
|
110
175
|
},
|
|
111
176
|
});
|
|
112
177
|
}
|
|
@@ -117,8 +182,19 @@ export const createLayers = (topology: Topology, features: Features, styles: Sty
|
|
|
117
182
|
|
|
118
183
|
/**
|
|
119
184
|
* Render layers created above.
|
|
185
|
+
*
|
|
186
|
+
* When `viewCenter` is supplied (orthographic globe), layers with a
|
|
187
|
+
* `cullable` index are filtered to just the features whose bounding circle
|
|
188
|
+
* intersects the visible hemisphere — keeping the d3-geo walk proportional
|
|
189
|
+
* to what's actually on-screen.
|
|
120
190
|
*/
|
|
121
|
-
export const renderLayers = (
|
|
191
|
+
export const renderLayers = (
|
|
192
|
+
generator: GeoPath,
|
|
193
|
+
layers: Layer[] = [],
|
|
194
|
+
scale: number,
|
|
195
|
+
styles: StyleSet,
|
|
196
|
+
viewCenter?: [number, number],
|
|
197
|
+
) => {
|
|
122
198
|
const context: CanvasRenderingContext2D = generator.context();
|
|
123
199
|
const {
|
|
124
200
|
canvas: { width, height },
|
|
@@ -135,7 +211,8 @@ export const renderLayers = (generator: GeoPath, layers: Layer[] = [], scale: nu
|
|
|
135
211
|
|
|
136
212
|
// Render features.
|
|
137
213
|
// https://github.com/d3/d3-geo#_path
|
|
138
|
-
layers.forEach((
|
|
214
|
+
layers.forEach((layer) => {
|
|
215
|
+
const { path, styles, cullable } = layer;
|
|
139
216
|
context.save();
|
|
140
217
|
let fill = false;
|
|
141
218
|
let stroke = false;
|
|
@@ -151,9 +228,21 @@ export const renderLayers = (generator: GeoPath, layers: Layer[] = [], scale: nu
|
|
|
151
228
|
});
|
|
152
229
|
}
|
|
153
230
|
|
|
154
|
-
|
|
231
|
+
let renderPath = path;
|
|
232
|
+
if (cullable && viewCenter) {
|
|
233
|
+
const geometries: Geometry[] = [];
|
|
234
|
+
for (let index = 0; index < cullable.length; index++) {
|
|
235
|
+
const bounds = cullable[index];
|
|
236
|
+
const angularDistance = geoDistance(viewCenter, bounds.centroid) * RAD_TO_DEG;
|
|
237
|
+
if (angularDistance < 90 + bounds.radius) {
|
|
238
|
+
geometries.push(bounds.geometry);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
renderPath = { type: 'GeometryCollection', geometries } as any;
|
|
242
|
+
}
|
|
155
243
|
|
|
156
|
-
|
|
244
|
+
context.beginPath();
|
|
245
|
+
generator(renderPath);
|
|
157
246
|
fill && context.fill();
|
|
158
247
|
stroke && context.stroke();
|
|
159
248
|
context.restore();
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2026 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { type ThemeMode } from '@dxos/react-ui';
|
|
6
|
+
|
|
7
|
+
import { type StyleSet } from './render';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Default style set for the Globe, theme-aware. Originated in plugin-map's
|
|
11
|
+
* GlobeControl; lifted here so other plugins (plugin-trip, etc.) get the same
|
|
12
|
+
* baseline without copying the palette.
|
|
13
|
+
*/
|
|
14
|
+
// Point colour; lines pick up the same colour at reduced alpha so the route
|
|
15
|
+
// reads as belonging to the same node set without competing with the nodes.
|
|
16
|
+
const POINT_COLOR = 'rgb(220, 38, 38)';
|
|
17
|
+
const LINE_COLOR = 'rgba(220, 38, 38, 0.5)';
|
|
18
|
+
|
|
19
|
+
export const globeStyles = (themeMode: ThemeMode): StyleSet =>
|
|
20
|
+
themeMode === 'dark'
|
|
21
|
+
? {
|
|
22
|
+
water: {
|
|
23
|
+
fillStyle: '#191919',
|
|
24
|
+
},
|
|
25
|
+
land: {
|
|
26
|
+
fillStyle: '#444',
|
|
27
|
+
strokeStyle: '#222',
|
|
28
|
+
},
|
|
29
|
+
border: {
|
|
30
|
+
strokeStyle: '#111',
|
|
31
|
+
},
|
|
32
|
+
graticule: {
|
|
33
|
+
strokeStyle: '#111',
|
|
34
|
+
},
|
|
35
|
+
line: {
|
|
36
|
+
lineWidth: 1.5,
|
|
37
|
+
lineDash: [4, 16],
|
|
38
|
+
strokeStyle: LINE_COLOR,
|
|
39
|
+
},
|
|
40
|
+
point: {
|
|
41
|
+
radius: 0.2,
|
|
42
|
+
fillStyle: POINT_COLOR,
|
|
43
|
+
},
|
|
44
|
+
}
|
|
45
|
+
: {
|
|
46
|
+
water: {
|
|
47
|
+
fillStyle: '#C0DAE4',
|
|
48
|
+
},
|
|
49
|
+
land: {
|
|
50
|
+
fillStyle: '#C2D8B4',
|
|
51
|
+
strokeStyle: '#A6C291',
|
|
52
|
+
},
|
|
53
|
+
line: {
|
|
54
|
+
lineWidth: 1.5,
|
|
55
|
+
lineDash: [4, 16],
|
|
56
|
+
strokeStyle: LINE_COLOR,
|
|
57
|
+
},
|
|
58
|
+
point: {
|
|
59
|
+
radius: 0.2,
|
|
60
|
+
fillStyle: POINT_COLOR,
|
|
61
|
+
},
|
|
62
|
+
};
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../../src/data.ts"],
|
|
4
|
-
"sourcesContent": ["//\n// Copyright 2024 DXOS.org\n//\n\nimport { type Topology } from 'topojson-specification';\n\nexport const loadTopology = async (): Promise<Topology> => {\n return (await import('../data/countries-110m.ts')).default;\n};\n"],
|
|
5
|
-
"mappings": ";AAMO,IAAMA,eAAe,YAAA;AAC1B,UAAQ,MAAM,OAAO,+BAAA,GAA8BC;AACrD;",
|
|
6
|
-
"names": ["loadTopology", "default"]
|
|
7
|
-
}
|