@mui/x-charts-premium 9.8.0 → 9.10.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/BarChartPremium/BarChartPremium.d.mts +1 -1
- package/BarChartPremium/BarChartPremium.d.ts +1 -1
- package/BarChartPremium/BarChartPremium.js +14 -3
- package/BarChartPremium/BarChartPremium.mjs +14 -3
- package/BarChartPremium/RangeBar/AnimatedRangeBarElement.d.mts +2 -1
- package/BarChartPremium/RangeBar/AnimatedRangeBarElement.d.ts +2 -1
- package/BarChartPremium/RangeBar/FocusedRangeBar.d.mts +1 -1
- package/BarChartPremium/RangeBar/FocusedRangeBar.d.ts +1 -1
- package/BarChartPremium/RangeBar/seriesConfig/getSeriesWithDefaultValues.d.mts +11 -11
- package/BarChartPremium/RangeBar/seriesConfig/getSeriesWithDefaultValues.d.ts +11 -11
- package/BarChartPremium/RangeBar/seriesConfig/index.js +2 -2
- package/BarChartPremium/RangeBar/seriesConfig/index.mjs +2 -2
- package/BarChartPremium/RangeBar/seriesConfig/tooltipPosition.d.mts +2 -3
- package/BarChartPremium/RangeBar/seriesConfig/tooltipPosition.d.ts +2 -3
- package/BarChartPremium/RangeBar/seriesConfig/tooltipPosition.js +12 -15
- package/BarChartPremium/RangeBar/seriesConfig/tooltipPosition.mjs +11 -14
- package/BarChartPremium/useBarChartPremiumProps.d.mts +3 -3
- package/BarChartPremium/useBarChartPremiumProps.d.ts +3 -3
- package/CHANGELOG.md +230 -0
- package/CandlestickChart/CandlestickPlot.d.mts +2 -1
- package/CandlestickChart/CandlestickPlot.d.ts +2 -1
- package/CandlestickChart/seriesConfig/OHLCTooltipContent.d.mts +2 -1
- package/CandlestickChart/seriesConfig/OHLCTooltipContent.d.ts +2 -1
- package/CandlestickChart/seriesConfig/getSeriesWithDefaultValues.d.mts +11 -11
- package/CandlestickChart/seriesConfig/getSeriesWithDefaultValues.d.ts +11 -11
- package/CandlestickChart/seriesConfig/index.js +2 -2
- package/CandlestickChart/seriesConfig/index.mjs +2 -2
- package/CandlestickChart/seriesConfig/tooltipPosition.d.mts +2 -3
- package/CandlestickChart/seriesConfig/tooltipPosition.d.ts +2 -3
- package/CandlestickChart/seriesConfig/tooltipPosition.js +10 -14
- package/CandlestickChart/seriesConfig/tooltipPosition.mjs +10 -14
- package/ChartsDataProviderPremium/ChartsDataProviderPremium.d.mts +1 -1
- package/ChartsDataProviderPremium/ChartsDataProviderPremium.d.ts +1 -1
- package/ChartsDataProviderPremium/ChartsDataProviderPremium.js +2 -2
- package/ChartsDataProviderPremium/ChartsDataProviderPremium.mjs +2 -2
- package/ChartsDataProviderPremium/useChartsDataProviderPremiumProps.d.mts +1 -1
- package/ChartsDataProviderPremium/useChartsDataProviderPremiumProps.d.ts +1 -1
- package/ChartsGeoDataProviderPremium/ChartsGeoDataProviderPremium.d.mts +1 -1
- package/ChartsGeoDataProviderPremium/ChartsGeoDataProviderPremium.d.ts +1 -1
- package/ChartsGeoDataProviderPremium/ChartsGeoDataProviderPremium.js +2 -2
- package/ChartsGeoDataProviderPremium/ChartsGeoDataProviderPremium.mjs +2 -2
- package/ChartsGeoDataProviderPremium/ChartsGeoDataProviderPremium.plugins.d.mts +4 -3
- package/ChartsGeoDataProviderPremium/ChartsGeoDataProviderPremium.plugins.d.ts +4 -3
- package/ChartsGeoDataProviderPremium/ChartsGeoDataProviderPremium.plugins.js +2 -1
- package/ChartsGeoDataProviderPremium/ChartsGeoDataProviderPremium.plugins.mjs +2 -1
- package/ChartsGeoDataProviderPremium/index.d.mts +2 -1
- package/ChartsGeoDataProviderPremium/index.d.ts +2 -1
- package/ChartsGeoDataProviderPremium/useChartsGeoDataProviderPremiumProps.d.mts +1 -1
- package/ChartsGeoDataProviderPremium/useChartsGeoDataProviderPremiumProps.d.ts +1 -1
- package/ChartsRadialDataProviderPremium/ChartsRadialDataProviderPremium.d.mts +2 -1
- package/ChartsRadialDataProviderPremium/ChartsRadialDataProviderPremium.d.ts +2 -1
- package/ChartsRadialDataProviderPremium/ChartsRadialDataProviderPremium.js +2 -2
- package/ChartsRadialDataProviderPremium/ChartsRadialDataProviderPremium.mjs +2 -2
- package/ChartsRadialDataProviderPremium/useChartsRadialDataProviderPremiumProps.d.mts +2 -3
- package/ChartsRadialDataProviderPremium/useChartsRadialDataProviderPremiumProps.d.ts +2 -3
- package/ChartsRenderer/components/PaletteOption.d.mts +1 -1
- package/ChartsRenderer/components/PaletteOption.d.ts +1 -1
- package/ChartsZoomSlider/internals/previews/CandlestickPreviewPlot.d.mts +2 -1
- package/ChartsZoomSlider/internals/previews/CandlestickPreviewPlot.d.ts +2 -1
- package/ChartsZoomSlider/internals/previews/RangeBarPreviewPlot.d.mts +1 -1
- package/ChartsZoomSlider/internals/previews/RangeBarPreviewPlot.d.ts +1 -1
- package/HeatmapPremium/HeatmapPlotPremium.d.mts +1 -1
- package/HeatmapPremium/HeatmapPlotPremium.d.ts +1 -1
- package/HeatmapPremium/useHeatmapPremiumProps.d.mts +2 -2
- package/HeatmapPremium/useHeatmapPremiumProps.d.ts +2 -2
- package/Map/FocusedMapShape.d.mts +2 -1
- package/Map/FocusedMapShape.d.ts +2 -1
- package/Map/GeoDataPlot.d.mts +1 -1
- package/Map/GeoDataPlot.d.ts +1 -1
- package/Map/Graticule.d.mts +1 -1
- package/Map/Graticule.d.ts +1 -1
- package/Map/MapImagePlot.d.mts +1 -1
- package/Map/MapImagePlot.d.ts +1 -1
- package/Map/MapShape.d.mts +1 -1
- package/Map/MapShape.d.ts +1 -1
- package/Map/MapShapePlot.d.mts +1 -1
- package/Map/MapShapePlot.d.ts +1 -1
- package/Map/index.d.mts +1 -3
- package/Map/index.d.ts +1 -3
- package/Map/seriesConfig/highlight.d.mts +2 -2
- package/Map/seriesConfig/highlight.d.ts +2 -2
- package/Map/seriesConfig/tooltipPosition.d.mts +1 -1
- package/Map/seriesConfig/tooltipPosition.d.ts +1 -1
- package/Map/seriesConfig/tooltipPosition.js +2 -8
- package/Map/seriesConfig/tooltipPosition.mjs +3 -9
- package/RadialBarChart/RadialBarElement.d.mts +1 -1
- package/RadialBarChart/RadialBarElement.d.ts +1 -1
- package/RadialBarChart/radialBarClasses.d.mts +1 -1
- package/RadialBarChart/radialBarClasses.d.ts +1 -1
- package/RadialBarChart/seriesConfig/index.js +2 -2
- package/RadialBarChart/seriesConfig/index.mjs +2 -2
- package/RadialBarChart/seriesConfig/tooltipPosition.d.mts +2 -3
- package/RadialBarChart/seriesConfig/tooltipPosition.d.ts +2 -3
- package/RadialBarChart/seriesConfig/tooltipPosition.js +4 -6
- package/RadialBarChart/seriesConfig/tooltipPosition.mjs +2 -5
- package/RadialLineChart/RadialArea.d.mts +2 -1
- package/RadialLineChart/RadialArea.d.ts +2 -1
- package/RadialLineChart/RadialAreaPlot.d.mts +1 -1
- package/RadialLineChart/RadialAreaPlot.d.ts +1 -1
- package/RadialLineChart/RadialLine.d.mts +1 -1
- package/RadialLineChart/RadialLine.d.ts +1 -1
- package/RadialLineChart/RadialLineHighlightElement.d.mts +1 -1
- package/RadialLineChart/RadialLineHighlightElement.d.ts +1 -1
- package/RadialLineChart/RadialLineHighlightPlot.d.mts +1 -1
- package/RadialLineChart/RadialLineHighlightPlot.d.ts +1 -1
- package/RadialLineChart/RadialLinePlot.d.mts +1 -1
- package/RadialLineChart/RadialLinePlot.d.ts +1 -1
- package/RadialLineChart/RadialMarkPlot.d.mts +1 -1
- package/RadialLineChart/RadialMarkPlot.d.ts +1 -1
- package/RadialLineChart/radialLineClasses.d.mts +1 -1
- package/RadialLineChart/radialLineClasses.d.ts +1 -1
- package/RadialLineChart/seriesConfig/index.js +2 -2
- package/RadialLineChart/seriesConfig/index.mjs +2 -2
- package/RadialLineChart/seriesConfig/tooltipPosition.d.mts +2 -3
- package/RadialLineChart/seriesConfig/tooltipPosition.d.ts +2 -3
- package/RadialLineChart/seriesConfig/tooltipPosition.js +4 -6
- package/RadialLineChart/seriesConfig/tooltipPosition.mjs +2 -5
- package/ScatterChartPremium/ScatterChartPremium.d.mts +2 -1
- package/ScatterChartPremium/ScatterChartPremium.d.ts +2 -1
- package/ScatterChartPremium/ScatterPlotPremium.d.mts +2 -1
- package/ScatterChartPremium/ScatterPlotPremium.d.ts +2 -1
- package/ScatterChartPremium/webgl/ScatterWebGLPlot.d.mts +2 -1
- package/ScatterChartPremium/webgl/ScatterWebGLPlot.d.ts +2 -1
- package/colorPalettes/complementary/candlestick.d.mts +2 -2
- package/colorPalettes/complementary/candlestick.d.ts +2 -2
- package/index.js +1 -1
- package/index.mjs +1 -1
- package/internals/plugins/allPlugins.d.mts +2 -2
- package/internals/plugins/allPlugins.d.ts +2 -2
- package/internals/plugins/useGeoProjection/factories.d.mts +3 -0
- package/internals/plugins/useGeoProjection/factories.d.ts +3 -0
- package/internals/plugins/useGeoProjection/factories.js +29 -0
- package/internals/plugins/useGeoProjection/factories.mjs +23 -0
- package/internals/plugins/useGeoProjection/projection.utils.d.mts +17 -0
- package/internals/plugins/useGeoProjection/projection.utils.d.ts +17 -0
- package/internals/plugins/useGeoProjection/projection.utils.js +67 -0
- package/internals/plugins/useGeoProjection/projection.utils.mjs +59 -0
- package/internals/plugins/useGeoProjection/useGeoProjection.js +7 -40
- package/internals/plugins/useGeoProjection/useGeoProjection.mjs +7 -40
- package/internals/plugins/useGeoProjection/useGeoProjection.selectors.d.mts +47 -11
- package/internals/plugins/useGeoProjection/useGeoProjection.selectors.d.ts +47 -11
- package/internals/plugins/useGeoProjection/useGeoProjection.selectors.js +118 -8
- package/internals/plugins/useGeoProjection/useGeoProjection.selectors.mjs +117 -8
- package/internals/plugins/useGeoProjection/useGeoProjection.types.d.mts +63 -2
- package/internals/plugins/useGeoProjection/useGeoProjection.types.d.ts +63 -2
- package/internals/plugins/useGeoProjectionZoom/gestureHooks/usePanOnDrag.d.mts +11 -0
- package/internals/plugins/useGeoProjectionZoom/gestureHooks/usePanOnDrag.d.ts +11 -0
- package/internals/plugins/useGeoProjectionZoom/gestureHooks/usePanOnDrag.js +65 -0
- package/internals/plugins/useGeoProjectionZoom/gestureHooks/usePanOnDrag.mjs +58 -0
- package/internals/plugins/useGeoProjectionZoom/gestureHooks/useZoomOnPinch.d.mts +13 -0
- package/internals/plugins/useGeoProjectionZoom/gestureHooks/useZoomOnPinch.d.ts +13 -0
- package/internals/plugins/useGeoProjectionZoom/gestureHooks/useZoomOnPinch.js +62 -0
- package/internals/plugins/useGeoProjectionZoom/gestureHooks/useZoomOnPinch.mjs +56 -0
- package/internals/plugins/useGeoProjectionZoom/gestureHooks/useZoomOnWheel.d.mts +13 -0
- package/internals/plugins/useGeoProjectionZoom/gestureHooks/useZoomOnWheel.d.ts +13 -0
- package/internals/plugins/useGeoProjectionZoom/gestureHooks/useZoomOnWheel.js +64 -0
- package/internals/plugins/useGeoProjectionZoom/gestureHooks/useZoomOnWheel.mjs +58 -0
- package/internals/plugins/useGeoProjectionZoom/index.d.mts +2 -0
- package/internals/plugins/useGeoProjectionZoom/index.d.ts +2 -0
- package/internals/plugins/useGeoProjectionZoom/index.js +12 -0
- package/internals/plugins/useGeoProjectionZoom/index.mjs +1 -0
- package/internals/plugins/useGeoProjectionZoom/mapZoom.utils.d.mts +31 -0
- package/internals/plugins/useGeoProjectionZoom/mapZoom.utils.d.ts +31 -0
- package/internals/plugins/useGeoProjectionZoom/mapZoom.utils.js +187 -0
- package/internals/plugins/useGeoProjectionZoom/mapZoom.utils.mjs +177 -0
- package/internals/plugins/useGeoProjectionZoom/rotationMath.d.mts +23 -0
- package/internals/plugins/useGeoProjectionZoom/rotationMath.d.ts +23 -0
- package/internals/plugins/useGeoProjectionZoom/rotationMath.js +190 -0
- package/internals/plugins/useGeoProjectionZoom/rotationMath.mjs +182 -0
- package/internals/plugins/useGeoProjectionZoom/useGeoProjectionZoom.d.mts +3 -0
- package/internals/plugins/useGeoProjectionZoom/useGeoProjectionZoom.d.ts +3 -0
- package/internals/plugins/useGeoProjectionZoom/useGeoProjectionZoom.js +174 -0
- package/internals/plugins/useGeoProjectionZoom/useGeoProjectionZoom.mjs +166 -0
- package/internals/plugins/useGeoProjectionZoom/useGeoProjectionZoom.types.d.mts +152 -0
- package/internals/plugins/useGeoProjectionZoom/useGeoProjectionZoom.types.d.ts +152 -0
- package/internals/plugins/useGeoProjectionZoom/useGeoProjectionZoom.types.js +5 -0
- package/internals/plugins/useGeoProjectionZoom/useGeoProjectionZoom.types.mjs +1 -0
- package/package.json +6 -6
- package/plugins/selectors/useChartCandlestickPosition.selectors.d.mts +1 -1
- package/plugins/selectors/useChartCandlestickPosition.selectors.d.ts +1 -1
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
const DEG = Math.PI / 180;
|
|
2
|
+
const clamp = (value, min, max) => Math.min(max, Math.max(min, value));
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Rotate a `[longitude, latitude]` coordinate around the projection's center axis (the x-axis
|
|
6
|
+
* pointing to `[0, 0]`) by `gamma` degrees.
|
|
7
|
+
*
|
|
8
|
+
* This is the roll component of a d3 rotation `[lambda, phi, gamma]`, isolated so it can be undone
|
|
9
|
+
* on the target coordinate before solving the longitude/latitude rotation. A d3 rotation composes as
|
|
10
|
+
* `rollGamma ∘ geoRotation([lambda, phi])`, so pre-applying `rollGamma(-gamma)` to the target keeps
|
|
11
|
+
* the roll fixed while the yaw/pitch solver stays a two-angle problem.
|
|
12
|
+
*/
|
|
13
|
+
function rollCoordinate(coord, gamma) {
|
|
14
|
+
if (!gamma) {
|
|
15
|
+
return coord;
|
|
16
|
+
}
|
|
17
|
+
const g = gamma * DEG;
|
|
18
|
+
const cosG = Math.cos(g);
|
|
19
|
+
const sinG = Math.sin(g);
|
|
20
|
+
const lon = coord[0] * DEG;
|
|
21
|
+
const lat = coord[1] * DEG;
|
|
22
|
+
const x = Math.cos(lon) * Math.cos(lat);
|
|
23
|
+
const y = Math.sin(lon) * Math.cos(lat);
|
|
24
|
+
const z = Math.sin(lat);
|
|
25
|
+
// Rotation about the x-axis by `g`.
|
|
26
|
+
const yRolled = y * cosG - z * sinG;
|
|
27
|
+
const zRolled = y * sinG + z * cosG;
|
|
28
|
+
return [Math.atan2(yRolled, x) / DEG, Math.asin(clamp(zRolled, -1, 1)) / DEG];
|
|
29
|
+
}
|
|
30
|
+
const cross = (a, b) => [a[1] * b[2] - a[2] * b[1], a[2] * b[0] - a[0] * b[2], a[0] * b[1] - a[1] * b[0]];
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Unit vector on the sphere for a `[longitude, latitude]` coordinate (degrees).
|
|
34
|
+
*/
|
|
35
|
+
function unitVector([lonDeg, latDeg]) {
|
|
36
|
+
const lon = lonDeg * DEG;
|
|
37
|
+
const lat = latDeg * DEG;
|
|
38
|
+
const cosLat = Math.cos(lat);
|
|
39
|
+
return [Math.cos(lon) * cosLat, Math.sin(lon) * cosLat, Math.sin(lat)];
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Rotate vector `v` around the unit axis `k` by `angle` radians (Rodrigues' rotation formula).
|
|
44
|
+
*/
|
|
45
|
+
function rotateAroundAxis(k, angle, v) {
|
|
46
|
+
const cos = Math.cos(angle);
|
|
47
|
+
const sin = Math.sin(angle);
|
|
48
|
+
const dot = (k[0] * v[0] + k[1] * v[1] + k[2] * v[2]) * (1 - cos);
|
|
49
|
+
const kv = cross(k, v);
|
|
50
|
+
return [v[0] * cos + kv[0] * sin + k[0] * dot, v[1] * cos + kv[1] * sin + k[1] * dot, v[2] * cos + kv[2] * sin + k[2] * dot];
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Given the current d3 `rotate` `[lambda, phi, gamma]` (degrees), returns the new
|
|
55
|
+
* `[longitude, latitude, roll]` (the view `center` plus `roll`) that drags `geoPoint` onto the
|
|
56
|
+
* identity-frame screen coordinate `q` using the shortest-arc rotation composed with the current
|
|
57
|
+
* orientation. Because the delta is the minimal rotation moving the grabbed point to the target, the
|
|
58
|
+
* roll only changes as much as strictly required.
|
|
59
|
+
*/
|
|
60
|
+
export function getMinimalRollRotation(rotate, geoPoint, targetGeoPoint) {
|
|
61
|
+
const l = rotate[0] * DEG;
|
|
62
|
+
const p = rotate[1] * DEG;
|
|
63
|
+
const g = (rotate[2] ?? 0) * DEG;
|
|
64
|
+
const cl = Math.cos(l);
|
|
65
|
+
const sl = Math.sin(l);
|
|
66
|
+
const cp = Math.cos(p);
|
|
67
|
+
const sp = Math.sin(p);
|
|
68
|
+
const cg = Math.cos(g);
|
|
69
|
+
const sg = Math.sin(g);
|
|
70
|
+
|
|
71
|
+
// Columns of the current rotation matrix `M = Rx(g)·Ry(-p)·Rz(l)`, which is exactly
|
|
72
|
+
// d3's `geoRotation([lambda, phi, gamma])` expressed on cartesian unit vectors.
|
|
73
|
+
const col0 = [cp * cl, cg * sl - sg * sp * cl, sg * sl + cg * sp * cl];
|
|
74
|
+
const col1 = [-cp * sl, cg * cl + sg * sp * sl, sg * cl - cg * sp * sl];
|
|
75
|
+
const col2 = [-sp, -sg * cp, cg * cp];
|
|
76
|
+
const point = unitVector(geoPoint);
|
|
77
|
+
// Where the grabbed point currently sits in the identity (screen) frame: `M · point`.
|
|
78
|
+
const current = [col0[0] * point[0] + col1[0] * point[1] + col2[0] * point[2], col0[1] * point[0] + col1[1] * point[1] + col2[1] * point[2], col0[2] * point[0] + col1[2] * point[1] + col2[2] * point[2]];
|
|
79
|
+
const target = unitVector(targetGeoPoint);
|
|
80
|
+
|
|
81
|
+
// Shortest-arc rotation taking `current` onto `target`, applied to `M` column by column
|
|
82
|
+
// (`M_new = delta · M`).
|
|
83
|
+
const axis = cross(current, target);
|
|
84
|
+
const s = Math.hypot(axis[0], axis[1], axis[2]);
|
|
85
|
+
let n0 = col0;
|
|
86
|
+
let n1 = col1;
|
|
87
|
+
let n2 = col2;
|
|
88
|
+
if (s > 1e-12) {
|
|
89
|
+
const dot = clamp(current[0] * target[0] + current[1] * target[1] + current[2] * target[2], -1, 1);
|
|
90
|
+
const angle = Math.atan2(s, dot);
|
|
91
|
+
const k = [axis[0] / s, axis[1] / s, axis[2] / s];
|
|
92
|
+
n0 = rotateAroundAxis(k, angle, col0);
|
|
93
|
+
n1 = rotateAroundAxis(k, angle, col1);
|
|
94
|
+
n2 = rotateAroundAxis(k, angle, col2);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Decompose `M_new = Rx(g')·Ry(-p')·Rz(l')` back into d3 angles.
|
|
98
|
+
const phi = Math.asin(clamp(-n2[0], -1, 1));
|
|
99
|
+
const lambda = Math.atan2(-n1[0], n0[0]);
|
|
100
|
+
const gamma = Math.atan2(-n2[1], n2[2]);
|
|
101
|
+
|
|
102
|
+
// `rotate = [-center[0], -center[1], roll]`, so invert the sign for the view center.
|
|
103
|
+
return [-lambda / DEG, -phi / DEG, gamma / DEG];
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Given the current d3 `rotate` `[lambda, phi, gamma]` (degrees), returns the
|
|
108
|
+
* `[longitude, latitude, roll]` that drags `geoPoint` onto the identity-frame screen coordinate
|
|
109
|
+
* `targetGeoPoint` while keeping the roll (`gamma`) unchanged: only the longitude and latitude move.
|
|
110
|
+
* When the target is out of reach for a roll-preserving rotation, the closest reachable orientation
|
|
111
|
+
* is returned.
|
|
112
|
+
*/
|
|
113
|
+
export function getNoRollRotation(rotate, geoPoint, targetGeoPoint) {
|
|
114
|
+
const roll = rotate[2] ?? 0;
|
|
115
|
+
|
|
116
|
+
// A d3 rotation composes as `rollGamma ∘ geoRotation([lambda, phi])`, so undo the roll on the
|
|
117
|
+
// target: what remains is a plain (roll-free) `Ry(-phi)·Rz(lambda)` mapping `geoPoint` onto it.
|
|
118
|
+
const [px, py, pz] = unitVector(geoPoint);
|
|
119
|
+
const [tx, ty, tz] = unitVector(rollCoordinate(targetGeoPoint, -roll));
|
|
120
|
+
const lambdaOld = rotate[0] * DEG;
|
|
121
|
+
const phiOld = rotate[1] * DEG;
|
|
122
|
+
|
|
123
|
+
// `Rz(lambda)` spins `geoPoint` on the circle of radius `r` in the xy-plane, keeping its
|
|
124
|
+
// z-component; `Ry(-phi)` then tilts it. So after `Rz` the y-component (`uy`) must already equal
|
|
125
|
+
// the target's, and the xy-radius bounds how far the latitude can reach.
|
|
126
|
+
const r = Math.hypot(px, py);
|
|
127
|
+
if (r < 1e-12) {
|
|
128
|
+
// `geoPoint` sits on a pole where `Rz(lambda)` is a no-op: keep the current longitude and only
|
|
129
|
+
// solve the tilt.
|
|
130
|
+
const phi = Math.atan2(tz, tx) - Math.atan2(pz, 0);
|
|
131
|
+
return [-lambdaOld / DEG, -phi / DEG, roll];
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// `clamp` keeps the nearest reachable point when the target latitude is out of range (`|ty| > r`).
|
|
135
|
+
const uy = clamp(ty, -r, r);
|
|
136
|
+
const uxMagnitude = Math.sqrt(Math.max(0, r * r - uy * uy));
|
|
137
|
+
const solveFor = ux => ({
|
|
138
|
+
// `Rz(lambda)` rotates `(px, py)` onto `(ux, uy)`.
|
|
139
|
+
lambda: Math.atan2(uy, ux) - Math.atan2(py, px),
|
|
140
|
+
// `Ry(-phi)` rotates `(ux, pz)` onto `(tx, tz)`.
|
|
141
|
+
phi: Math.atan2(tz, tx) - Math.atan2(pz, ux)
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
// Two branches (`±ux`) solve the equation; pick the one closest to the current orientation so the
|
|
145
|
+
// rotation stays continuous while dragging.
|
|
146
|
+
const wrap = angle => Math.atan2(Math.sin(angle), Math.cos(angle));
|
|
147
|
+
const distanceToCurrent = ({
|
|
148
|
+
lambda,
|
|
149
|
+
phi
|
|
150
|
+
}) => Math.abs(wrap(lambda - lambdaOld)) + Math.abs(wrap(phi - phiOld));
|
|
151
|
+
const positive = solveFor(uxMagnitude);
|
|
152
|
+
const negative = solveFor(-uxMagnitude);
|
|
153
|
+
const best = distanceToCurrent(positive) <= distanceToCurrent(negative) ? positive : negative;
|
|
154
|
+
return [-best.lambda / DEG, -best.phi / DEG, roll];
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Given the current d3 `rotate` `[lambda, phi, gamma]` (degrees), returns the
|
|
159
|
+
* `[longitude, latitude, roll]` that pans `geoPoint` toward the identity-frame screen coordinate
|
|
160
|
+
* `targetGeoPoint` along the longitude axis only: the latitude and roll are left untouched and just
|
|
161
|
+
* the longitude is solved so `geoPoint` reaches the target's longitude.
|
|
162
|
+
*/
|
|
163
|
+
export function getLongitudeRotation(rotate, geoPoint, targetGeoPoint) {
|
|
164
|
+
const roll = rotate[2] ?? 0;
|
|
165
|
+
const latitude = -rotate[1]; // the fixed center latitude (degrees)
|
|
166
|
+
|
|
167
|
+
// Undo the roll on the target, then keep the pitch locked to the current latitude and solve the
|
|
168
|
+
// yaw so `geoPoint` lands on the target's longitude.
|
|
169
|
+
const [tx, ty, tz] = unitVector(rollCoordinate(targetGeoPoint, -roll));
|
|
170
|
+
const lonG = geoPoint[0] * DEG;
|
|
171
|
+
const c1 = latitude * DEG;
|
|
172
|
+
const c0 = lonG - Math.atan2(ty, tx * Math.cos(c1) - tz * Math.sin(c1));
|
|
173
|
+
|
|
174
|
+
// Normalize the longitude into `[-180, 180]`.
|
|
175
|
+
let longitude = c0 / DEG % 360;
|
|
176
|
+
if (longitude > 180) {
|
|
177
|
+
longitude -= 360;
|
|
178
|
+
} else if (longitude < -180) {
|
|
179
|
+
longitude += 360;
|
|
180
|
+
}
|
|
181
|
+
return [longitude, latitude, roll];
|
|
182
|
+
}
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
'use client';
|
|
3
|
+
|
|
4
|
+
var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard").default;
|
|
5
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
|
|
6
|
+
Object.defineProperty(exports, "__esModule", {
|
|
7
|
+
value: true
|
|
8
|
+
});
|
|
9
|
+
exports.useGeoProjectionZoom = void 0;
|
|
10
|
+
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
|
|
11
|
+
var React = _interopRequireWildcard(require("react"));
|
|
12
|
+
var _useEffectAfterFirstRender = require("@mui/x-internals/useEffectAfterFirstRender");
|
|
13
|
+
var _internals = require("@mui/x-charts-pro/internals");
|
|
14
|
+
var _useGeoProjection = require("../useGeoProjection/useGeoProjection.selectors");
|
|
15
|
+
var _mapZoom = require("./mapZoom.utils");
|
|
16
|
+
var _usePanOnDrag = require("./gestureHooks/usePanOnDrag");
|
|
17
|
+
var _useZoomOnWheel = require("./gestureHooks/useZoomOnWheel");
|
|
18
|
+
var _useZoomOnPinch = require("./gestureHooks/useZoomOnPinch");
|
|
19
|
+
var _projection = require("../useGeoProjection/projection.utils");
|
|
20
|
+
const useGeoProjectionZoom = ({
|
|
21
|
+
store,
|
|
22
|
+
instance,
|
|
23
|
+
params
|
|
24
|
+
}) => {
|
|
25
|
+
const {
|
|
26
|
+
zoom,
|
|
27
|
+
onViewChange,
|
|
28
|
+
view
|
|
29
|
+
} = params;
|
|
30
|
+
const interactionDefaults = (0, _mapZoom.getDefaultMapInteraction)((0, _useGeoProjection.selectorChartRawProjection)(store.state));
|
|
31
|
+
const {
|
|
32
|
+
minZoomLevel = 0.5,
|
|
33
|
+
maxZoomLevel = 8,
|
|
34
|
+
maxEmptySpace = 0,
|
|
35
|
+
rotationAllowed = interactionDefaults.rotationAllowed,
|
|
36
|
+
translationAllowed = interactionDefaults.translationAllowed
|
|
37
|
+
} = typeof zoom === 'object' ? zoom : {};
|
|
38
|
+
|
|
39
|
+
// `zoom` is either a boolean or a config object; an object always enables the interaction.
|
|
40
|
+
const enabled = zoom !== false;
|
|
41
|
+
const isControlled = view !== undefined;
|
|
42
|
+
const clampZoomLevel = React.useCallback(zoomLevel => Math.max(minZoomLevel, Math.min(maxZoomLevel, zoomLevel)), [minZoomLevel, maxZoomLevel]);
|
|
43
|
+
|
|
44
|
+
// The view is the source of truth, stored directly: no pixel <-> view conversion on write/read.
|
|
45
|
+
// Callers are responsible for clamping `zoomLevel`.
|
|
46
|
+
const applyView = React.useCallback(newView => {
|
|
47
|
+
if (!isControlled) {
|
|
48
|
+
store.set('geoProjectionZoom', (0, _extends2.default)({}, store.state.geoProjectionZoom, {
|
|
49
|
+
zoomLevel: newView.zoomLevel,
|
|
50
|
+
center: newView.center,
|
|
51
|
+
translation: newView.translation,
|
|
52
|
+
roll: newView.roll
|
|
53
|
+
}));
|
|
54
|
+
}
|
|
55
|
+
onViewChange?.(newView);
|
|
56
|
+
}, [store, isControlled, onViewChange]);
|
|
57
|
+
|
|
58
|
+
// In controlled mode, keep the store in sync with the `view` prop. The initial view is seeded in
|
|
59
|
+
// `getInitialState`, so this only reacts to subsequent updates.
|
|
60
|
+
(0, _useEffectAfterFirstRender.useEffectAfterFirstRender)(() => {
|
|
61
|
+
if (!view) {
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
store.set('geoProjectionZoom', (0, _extends2.default)({}, store.state.geoProjectionZoom, {
|
|
65
|
+
zoomLevel: view.zoomLevel,
|
|
66
|
+
center: view.center,
|
|
67
|
+
translation: view.translation,
|
|
68
|
+
roll: view.roll
|
|
69
|
+
}));
|
|
70
|
+
}, [store, view]);
|
|
71
|
+
(0, _internals.useRegisterZoomGestures)({
|
|
72
|
+
instance
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
// --- gestures: reuse the generic primitives from x-charts-pro -------------
|
|
76
|
+
(0, _usePanOnDrag.usePanOnDrag)({
|
|
77
|
+
store,
|
|
78
|
+
instance
|
|
79
|
+
}, applyView, {
|
|
80
|
+
enabled,
|
|
81
|
+
rotationAllowed,
|
|
82
|
+
translationAllowed,
|
|
83
|
+
maxEmptySpace
|
|
84
|
+
});
|
|
85
|
+
(0, _useZoomOnWheel.useZoomOnWheel)({
|
|
86
|
+
store,
|
|
87
|
+
instance
|
|
88
|
+
}, applyView, {
|
|
89
|
+
enabled,
|
|
90
|
+
rotationAllowed,
|
|
91
|
+
translationAllowed,
|
|
92
|
+
maxEmptySpace,
|
|
93
|
+
minZoomLevel,
|
|
94
|
+
maxZoomLevel
|
|
95
|
+
});
|
|
96
|
+
(0, _useZoomOnPinch.useZoomOnPinch)({
|
|
97
|
+
store,
|
|
98
|
+
instance
|
|
99
|
+
}, applyView, {
|
|
100
|
+
enabled,
|
|
101
|
+
rotationAllowed,
|
|
102
|
+
translationAllowed,
|
|
103
|
+
maxEmptySpace,
|
|
104
|
+
minZoomLevel,
|
|
105
|
+
maxZoomLevel
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
// Shared by both buttons: clamp through `applyView` (which also handles controlled mode and
|
|
109
|
+
// `onViewChange`), keeping the current center/translation. Bail out when already at a bound so a
|
|
110
|
+
// click at the limit stays a no-op.
|
|
111
|
+
const zoomBy = React.useCallback(factor => {
|
|
112
|
+
const current = store.state.geoProjectionZoom;
|
|
113
|
+
const currentZoom = current.zoomLevel ?? 1;
|
|
114
|
+
const nextZoom = clampZoomLevel(currentZoom * factor);
|
|
115
|
+
if (nextZoom === currentZoom) {
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
applyView({
|
|
119
|
+
zoomLevel: nextZoom,
|
|
120
|
+
center: current.center ?? [0, 0],
|
|
121
|
+
translation: current.translation ?? [0, 0],
|
|
122
|
+
roll: current.roll ?? 0
|
|
123
|
+
});
|
|
124
|
+
}, [store, clampZoomLevel, applyView]);
|
|
125
|
+
const zoomIn = React.useCallback(() => zoomBy(_mapZoom.BUTTON_ZOOM_STEP), [zoomBy]);
|
|
126
|
+
const zoomOut = React.useCallback(() => zoomBy(1 / _mapZoom.BUTTON_ZOOM_STEP), [zoomBy]);
|
|
127
|
+
const resetZoom = React.useCallback(() => {
|
|
128
|
+
applyView({
|
|
129
|
+
zoomLevel: store.state.geoProjectionZoom.initialZoomLevel,
|
|
130
|
+
center: store.state.geoProjectionZoom.initialCenter,
|
|
131
|
+
translation: store.state.geoProjectionZoom.initialTranslation,
|
|
132
|
+
roll: store.state.geoProjectionZoom.initialRoll
|
|
133
|
+
});
|
|
134
|
+
}, [applyView, store]);
|
|
135
|
+
const publicAPI = {
|
|
136
|
+
zoomIn,
|
|
137
|
+
zoomOut,
|
|
138
|
+
resetZoom
|
|
139
|
+
};
|
|
140
|
+
return {
|
|
141
|
+
publicAPI,
|
|
142
|
+
instance: publicAPI
|
|
143
|
+
};
|
|
144
|
+
};
|
|
145
|
+
exports.useGeoProjectionZoom = useGeoProjectionZoom;
|
|
146
|
+
useGeoProjectionZoom.params = {
|
|
147
|
+
zoom: true,
|
|
148
|
+
initialView: true,
|
|
149
|
+
view: true,
|
|
150
|
+
onViewChange: true
|
|
151
|
+
};
|
|
152
|
+
useGeoProjectionZoom.getDefaultizedParams = ({
|
|
153
|
+
params
|
|
154
|
+
}) => (0, _extends2.default)({}, params, {
|
|
155
|
+
zoom: params.zoom ?? false
|
|
156
|
+
});
|
|
157
|
+
useGeoProjectionZoom.getInitialState = params => {
|
|
158
|
+
const zoomLevel = params.view?.zoomLevel ?? params.initialView?.zoomLevel ?? 1;
|
|
159
|
+
const center = params.view?.center ?? params.initialView?.center ?? [0, 0];
|
|
160
|
+
const roll = params.view?.roll ?? params.initialView?.roll ?? 0;
|
|
161
|
+
const translation = params.view?.translation ?? params.initialView?.translation ?? (0, _projection.getDefaultTranslation)(params.projection, params.geoData, params.parallels, center) ?? [0, 0];
|
|
162
|
+
return {
|
|
163
|
+
geoProjectionZoom: {
|
|
164
|
+
zoomLevel,
|
|
165
|
+
center,
|
|
166
|
+
translation,
|
|
167
|
+
roll,
|
|
168
|
+
initialZoomLevel: zoomLevel,
|
|
169
|
+
initialCenter: center,
|
|
170
|
+
initialTranslation: translation,
|
|
171
|
+
initialRoll: roll
|
|
172
|
+
}
|
|
173
|
+
};
|
|
174
|
+
};
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import _extends from "@babel/runtime/helpers/esm/extends";
|
|
4
|
+
import * as React from 'react';
|
|
5
|
+
import { useEffectAfterFirstRender } from '@mui/x-internals/useEffectAfterFirstRender';
|
|
6
|
+
import { useRegisterZoomGestures } from '@mui/x-charts-pro/internals';
|
|
7
|
+
import { selectorChartRawProjection } from "../useGeoProjection/useGeoProjection.selectors.mjs";
|
|
8
|
+
import { BUTTON_ZOOM_STEP, getDefaultMapInteraction } from "./mapZoom.utils.mjs";
|
|
9
|
+
import { usePanOnDrag } from "./gestureHooks/usePanOnDrag.mjs";
|
|
10
|
+
import { useZoomOnWheel } from "./gestureHooks/useZoomOnWheel.mjs";
|
|
11
|
+
import { useZoomOnPinch } from "./gestureHooks/useZoomOnPinch.mjs";
|
|
12
|
+
import { getDefaultTranslation } from "../useGeoProjection/projection.utils.mjs";
|
|
13
|
+
export const useGeoProjectionZoom = ({
|
|
14
|
+
store,
|
|
15
|
+
instance,
|
|
16
|
+
params
|
|
17
|
+
}) => {
|
|
18
|
+
const {
|
|
19
|
+
zoom,
|
|
20
|
+
onViewChange,
|
|
21
|
+
view
|
|
22
|
+
} = params;
|
|
23
|
+
const interactionDefaults = getDefaultMapInteraction(selectorChartRawProjection(store.state));
|
|
24
|
+
const {
|
|
25
|
+
minZoomLevel = 0.5,
|
|
26
|
+
maxZoomLevel = 8,
|
|
27
|
+
maxEmptySpace = 0,
|
|
28
|
+
rotationAllowed = interactionDefaults.rotationAllowed,
|
|
29
|
+
translationAllowed = interactionDefaults.translationAllowed
|
|
30
|
+
} = typeof zoom === 'object' ? zoom : {};
|
|
31
|
+
|
|
32
|
+
// `zoom` is either a boolean or a config object; an object always enables the interaction.
|
|
33
|
+
const enabled = zoom !== false;
|
|
34
|
+
const isControlled = view !== undefined;
|
|
35
|
+
const clampZoomLevel = React.useCallback(zoomLevel => Math.max(minZoomLevel, Math.min(maxZoomLevel, zoomLevel)), [minZoomLevel, maxZoomLevel]);
|
|
36
|
+
|
|
37
|
+
// The view is the source of truth, stored directly: no pixel <-> view conversion on write/read.
|
|
38
|
+
// Callers are responsible for clamping `zoomLevel`.
|
|
39
|
+
const applyView = React.useCallback(newView => {
|
|
40
|
+
if (!isControlled) {
|
|
41
|
+
store.set('geoProjectionZoom', _extends({}, store.state.geoProjectionZoom, {
|
|
42
|
+
zoomLevel: newView.zoomLevel,
|
|
43
|
+
center: newView.center,
|
|
44
|
+
translation: newView.translation,
|
|
45
|
+
roll: newView.roll
|
|
46
|
+
}));
|
|
47
|
+
}
|
|
48
|
+
onViewChange?.(newView);
|
|
49
|
+
}, [store, isControlled, onViewChange]);
|
|
50
|
+
|
|
51
|
+
// In controlled mode, keep the store in sync with the `view` prop. The initial view is seeded in
|
|
52
|
+
// `getInitialState`, so this only reacts to subsequent updates.
|
|
53
|
+
useEffectAfterFirstRender(() => {
|
|
54
|
+
if (!view) {
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
store.set('geoProjectionZoom', _extends({}, store.state.geoProjectionZoom, {
|
|
58
|
+
zoomLevel: view.zoomLevel,
|
|
59
|
+
center: view.center,
|
|
60
|
+
translation: view.translation,
|
|
61
|
+
roll: view.roll
|
|
62
|
+
}));
|
|
63
|
+
}, [store, view]);
|
|
64
|
+
useRegisterZoomGestures({
|
|
65
|
+
instance
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
// --- gestures: reuse the generic primitives from x-charts-pro -------------
|
|
69
|
+
usePanOnDrag({
|
|
70
|
+
store,
|
|
71
|
+
instance
|
|
72
|
+
}, applyView, {
|
|
73
|
+
enabled,
|
|
74
|
+
rotationAllowed,
|
|
75
|
+
translationAllowed,
|
|
76
|
+
maxEmptySpace
|
|
77
|
+
});
|
|
78
|
+
useZoomOnWheel({
|
|
79
|
+
store,
|
|
80
|
+
instance
|
|
81
|
+
}, applyView, {
|
|
82
|
+
enabled,
|
|
83
|
+
rotationAllowed,
|
|
84
|
+
translationAllowed,
|
|
85
|
+
maxEmptySpace,
|
|
86
|
+
minZoomLevel,
|
|
87
|
+
maxZoomLevel
|
|
88
|
+
});
|
|
89
|
+
useZoomOnPinch({
|
|
90
|
+
store,
|
|
91
|
+
instance
|
|
92
|
+
}, applyView, {
|
|
93
|
+
enabled,
|
|
94
|
+
rotationAllowed,
|
|
95
|
+
translationAllowed,
|
|
96
|
+
maxEmptySpace,
|
|
97
|
+
minZoomLevel,
|
|
98
|
+
maxZoomLevel
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
// Shared by both buttons: clamp through `applyView` (which also handles controlled mode and
|
|
102
|
+
// `onViewChange`), keeping the current center/translation. Bail out when already at a bound so a
|
|
103
|
+
// click at the limit stays a no-op.
|
|
104
|
+
const zoomBy = React.useCallback(factor => {
|
|
105
|
+
const current = store.state.geoProjectionZoom;
|
|
106
|
+
const currentZoom = current.zoomLevel ?? 1;
|
|
107
|
+
const nextZoom = clampZoomLevel(currentZoom * factor);
|
|
108
|
+
if (nextZoom === currentZoom) {
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
applyView({
|
|
112
|
+
zoomLevel: nextZoom,
|
|
113
|
+
center: current.center ?? [0, 0],
|
|
114
|
+
translation: current.translation ?? [0, 0],
|
|
115
|
+
roll: current.roll ?? 0
|
|
116
|
+
});
|
|
117
|
+
}, [store, clampZoomLevel, applyView]);
|
|
118
|
+
const zoomIn = React.useCallback(() => zoomBy(BUTTON_ZOOM_STEP), [zoomBy]);
|
|
119
|
+
const zoomOut = React.useCallback(() => zoomBy(1 / BUTTON_ZOOM_STEP), [zoomBy]);
|
|
120
|
+
const resetZoom = React.useCallback(() => {
|
|
121
|
+
applyView({
|
|
122
|
+
zoomLevel: store.state.geoProjectionZoom.initialZoomLevel,
|
|
123
|
+
center: store.state.geoProjectionZoom.initialCenter,
|
|
124
|
+
translation: store.state.geoProjectionZoom.initialTranslation,
|
|
125
|
+
roll: store.state.geoProjectionZoom.initialRoll
|
|
126
|
+
});
|
|
127
|
+
}, [applyView, store]);
|
|
128
|
+
const publicAPI = {
|
|
129
|
+
zoomIn,
|
|
130
|
+
zoomOut,
|
|
131
|
+
resetZoom
|
|
132
|
+
};
|
|
133
|
+
return {
|
|
134
|
+
publicAPI,
|
|
135
|
+
instance: publicAPI
|
|
136
|
+
};
|
|
137
|
+
};
|
|
138
|
+
useGeoProjectionZoom.params = {
|
|
139
|
+
zoom: true,
|
|
140
|
+
initialView: true,
|
|
141
|
+
view: true,
|
|
142
|
+
onViewChange: true
|
|
143
|
+
};
|
|
144
|
+
useGeoProjectionZoom.getDefaultizedParams = ({
|
|
145
|
+
params
|
|
146
|
+
}) => _extends({}, params, {
|
|
147
|
+
zoom: params.zoom ?? false
|
|
148
|
+
});
|
|
149
|
+
useGeoProjectionZoom.getInitialState = params => {
|
|
150
|
+
const zoomLevel = params.view?.zoomLevel ?? params.initialView?.zoomLevel ?? 1;
|
|
151
|
+
const center = params.view?.center ?? params.initialView?.center ?? [0, 0];
|
|
152
|
+
const roll = params.view?.roll ?? params.initialView?.roll ?? 0;
|
|
153
|
+
const translation = params.view?.translation ?? params.initialView?.translation ?? getDefaultTranslation(params.projection, params.geoData, params.parallels, center) ?? [0, 0];
|
|
154
|
+
return {
|
|
155
|
+
geoProjectionZoom: {
|
|
156
|
+
zoomLevel,
|
|
157
|
+
center,
|
|
158
|
+
translation,
|
|
159
|
+
roll,
|
|
160
|
+
initialZoomLevel: zoomLevel,
|
|
161
|
+
initialCenter: center,
|
|
162
|
+
initialTranslation: translation,
|
|
163
|
+
initialRoll: roll
|
|
164
|
+
}
|
|
165
|
+
};
|
|
166
|
+
};
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import type { ChartPluginSignature } from '@mui/x-charts/internals';
|
|
2
|
+
import type { UseGeoProjectionSignature } from "../useGeoProjection/useGeoProjection.types.mjs";
|
|
3
|
+
/**
|
|
4
|
+
* Which rotation axes a pan/zoom gesture may move:
|
|
5
|
+
* - `'both'`: rotate freely along longitude and latitude, keeping the roll fixed.
|
|
6
|
+
* - `'longitude'`: rotate along longitude only (lock the north–south tilt).
|
|
7
|
+
* - `'none'`: lock every axis.
|
|
8
|
+
* - `'both+roll'`: rotate freely along longitude and latitude, and allow rolling the map around the center.
|
|
9
|
+
*/
|
|
10
|
+
export type MapRotationAxis = 'both' | 'longitude' | 'none' | 'both+roll';
|
|
11
|
+
export type MapTranslationAxis = 'both' | 'x' | 'y' | 'none';
|
|
12
|
+
/**
|
|
13
|
+
* Public, resolution-independent representation of the map view.
|
|
14
|
+
*
|
|
15
|
+
* Unlike the raw projection `scale`/`translate` (both in SVG pixels, tied to the drawing-area
|
|
16
|
+
* size), a view survives a resize: `zoomLevel` is a ratio and `center` is a geographic coordinate.
|
|
17
|
+
*/
|
|
18
|
+
export interface MapZoomView {
|
|
19
|
+
/**
|
|
20
|
+
* The zoom level, as a multiple of the scale that fits the data in the drawing area.
|
|
21
|
+
* `1` means the whole dataset fits the drawing area; `2` means twice as close.
|
|
22
|
+
*/
|
|
23
|
+
zoomLevel: number;
|
|
24
|
+
/**
|
|
25
|
+
* The geographic coordinate `[longitude, latitude]` displayed at the center of the drawing area.
|
|
26
|
+
*/
|
|
27
|
+
center: [number, number];
|
|
28
|
+
/**
|
|
29
|
+
* The map translation in percentage of the drawing area.
|
|
30
|
+
*/
|
|
31
|
+
translation: [number, number];
|
|
32
|
+
/**
|
|
33
|
+
* The roll of the map, in degrees.
|
|
34
|
+
* This spins the map around the point displayed at the center of the drawing area, independently
|
|
35
|
+
* of the `center` (which controls longitude/latitude).
|
|
36
|
+
*/
|
|
37
|
+
roll: number;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Fine-grained configuration for the map zoom/pan interaction, passed as the `zoom` parameter
|
|
41
|
+
* instead of a plain `true`.
|
|
42
|
+
*/
|
|
43
|
+
export interface MapZoomOptions {
|
|
44
|
+
/**
|
|
45
|
+
* Which axes the map can be rotated along while panning or zooming.
|
|
46
|
+
* For example, `'longitude'` lets the map rotate east–west but locks the north–south tilt.
|
|
47
|
+
*/
|
|
48
|
+
rotationAllowed?: MapRotationAxis;
|
|
49
|
+
/**
|
|
50
|
+
* Which axes the map can be translated along while panning or zooming.
|
|
51
|
+
* For example, `'y'` lets the map translate vertically but locks the horizontal movement.
|
|
52
|
+
*/
|
|
53
|
+
translationAllowed?: MapTranslationAxis;
|
|
54
|
+
/**
|
|
55
|
+
* The minimum zoom level, as a multiple of the scale that fits the data in the drawing area.
|
|
56
|
+
* @default 1
|
|
57
|
+
*/
|
|
58
|
+
minZoomLevel?: number;
|
|
59
|
+
/**
|
|
60
|
+
* The maximum zoom level, as a multiple of the scale that fits the data in the drawing area.
|
|
61
|
+
* @default 8
|
|
62
|
+
*/
|
|
63
|
+
maxZoomLevel?: number;
|
|
64
|
+
/**
|
|
65
|
+
* The maximal space left empty while panning, expressed as a ratio of the drawing area size.
|
|
66
|
+
* For example:
|
|
67
|
+
* - `0` keeps the map's bounding box flush with (or covering) the drawing area.
|
|
68
|
+
* - `0.5` lets the user pan until at most half of the drawing area is empty on a given side.
|
|
69
|
+
* @default 0
|
|
70
|
+
*/
|
|
71
|
+
maxEmptySpace?: number;
|
|
72
|
+
}
|
|
73
|
+
interface UseGeoProjectionZoomParameters {
|
|
74
|
+
/**
|
|
75
|
+
* If `true`, the map can be panned (drag) and zoomed (wheel / pinch).
|
|
76
|
+
* Pass a {@link MapZoomOptions} object to fine-tune the interaction, e.g. restrict rotation axes.
|
|
77
|
+
* @default false
|
|
78
|
+
*/
|
|
79
|
+
zoom?: boolean | MapZoomOptions;
|
|
80
|
+
/**
|
|
81
|
+
* The view to apply on mount, when the zoom is not controlled.
|
|
82
|
+
* Use this to seed the map at a specific zoom level and center without controlling it.
|
|
83
|
+
*/
|
|
84
|
+
initialView?: Omit<MapZoomView, 'translation' | 'roll'> & Partial<Pick<MapZoomView, 'translation' | 'roll'>>;
|
|
85
|
+
/**
|
|
86
|
+
* The view to display, in controlled mode.
|
|
87
|
+
* When set, the component does not update the view on its own — drive it from `onViewChange`.
|
|
88
|
+
*/
|
|
89
|
+
view?: MapZoomView;
|
|
90
|
+
/**
|
|
91
|
+
* Callback fired when the map zoom or pan changes (including programmatic reset).
|
|
92
|
+
* @param {MapZoomView} view The new zoom level and geographic center.
|
|
93
|
+
*/
|
|
94
|
+
onViewChange?: (view: MapZoomView) => void;
|
|
95
|
+
}
|
|
96
|
+
interface UseGeoProjectionZoomDefaultizedParameters extends UseGeoProjectionZoomParameters {
|
|
97
|
+
zoom: boolean | MapZoomOptions;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Imperative methods shared by the plugin `instance` and the public `apiRef`.
|
|
101
|
+
*/
|
|
102
|
+
interface UseGeoProjectionZoomPublicApi {
|
|
103
|
+
/**
|
|
104
|
+
* Zoom the map in by a fixed step, centered on the drawing area.
|
|
105
|
+
*/
|
|
106
|
+
zoomIn: () => void;
|
|
107
|
+
/**
|
|
108
|
+
* Zoom the map out by a fixed step, centered on the drawing area.
|
|
109
|
+
*/
|
|
110
|
+
zoomOut: () => void;
|
|
111
|
+
/**
|
|
112
|
+
* Reset the map to the default scale and translation that fit the data in the drawing area.
|
|
113
|
+
*/
|
|
114
|
+
resetZoom: () => void;
|
|
115
|
+
}
|
|
116
|
+
interface UseGeoProjectionZoomInstance extends UseGeoProjectionZoomPublicApi {}
|
|
117
|
+
export interface UseGeoProjectionZoomState {
|
|
118
|
+
geoProjectionZoom: {
|
|
119
|
+
/**
|
|
120
|
+
* The zoom level, as a multiple of the scale that fits the data in the drawing area.
|
|
121
|
+
* `null` (the default) and `1` both mean fit-to-data. The absolute projection scale is
|
|
122
|
+
* derived as `fitScale * zoomLevel`, so this stays valid across resizes.
|
|
123
|
+
*/
|
|
124
|
+
zoomLevel: number;
|
|
125
|
+
/**
|
|
126
|
+
* The geographic coordinate `[longitude, latitude]` displayed at the center of the drawing area.
|
|
127
|
+
* `null` keeps the data centered (the fit center).
|
|
128
|
+
*/
|
|
129
|
+
center: [number, number];
|
|
130
|
+
/**
|
|
131
|
+
* The map translation in percentage of the drawing area.
|
|
132
|
+
*/
|
|
133
|
+
translation: [number, number] | null;
|
|
134
|
+
/**
|
|
135
|
+
* The roll of the map, in degrees. `null` keeps the map upright (no roll).
|
|
136
|
+
*/
|
|
137
|
+
roll: number;
|
|
138
|
+
initialTranslation: [number, number];
|
|
139
|
+
initialCenter: [number, number];
|
|
140
|
+
initialZoomLevel: number;
|
|
141
|
+
initialRoll: number;
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
export type UseGeoProjectionZoomSignature = ChartPluginSignature<{
|
|
145
|
+
params: UseGeoProjectionZoomParameters;
|
|
146
|
+
defaultizedParams: UseGeoProjectionZoomDefaultizedParameters;
|
|
147
|
+
publicAPI: UseGeoProjectionZoomPublicApi;
|
|
148
|
+
instance: UseGeoProjectionZoomInstance;
|
|
149
|
+
state: UseGeoProjectionZoomState;
|
|
150
|
+
dependencies: [UseGeoProjectionSignature];
|
|
151
|
+
}>;
|
|
152
|
+
export {};
|