@mui/x-charts-premium 9.7.0 → 9.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/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/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/webgl/BarWebGLProgram.d.mts +4 -5
- package/BarChartPremium/webgl/BarWebGLProgram.d.ts +4 -5
- package/BarChartPremium/webgl/BarWebGLProgram.js +24 -65
- package/BarChartPremium/webgl/BarWebGLProgram.mjs +24 -65
- package/BarChartPremium/webgl/shaders.d.mts +1 -1
- package/BarChartPremium/webgl/shaders.d.ts +1 -1
- package/BarChartPremium/webgl/shaders.js +2 -15
- package/BarChartPremium/webgl/shaders.mjs +3 -15
- package/CHANGELOG.md +249 -1
- 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/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/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/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/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/webgl/HeatmapWebGLProgram.js +12 -37
- package/HeatmapPremium/webgl/HeatmapWebGLProgram.mjs +12 -37
- package/HeatmapPremium/webgl/shaders.d.mts +3 -3
- package/HeatmapPremium/webgl/shaders.d.ts +3 -3
- package/HeatmapPremium/webgl/shaders.js +12 -15
- package/HeatmapPremium/webgl/shaders.mjs +13 -15
- package/HeatmapPremium/webgl/useHeatmapPlotData.js +3 -8
- package/HeatmapPremium/webgl/useHeatmapPlotData.mjs +3 -8
- package/Map/FocusedMapShape.d.mts +2 -1
- package/Map/FocusedMapShape.d.ts +2 -1
- package/Map/FocusedMapShape.js +5 -1
- package/Map/FocusedMapShape.mjs +5 -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 +39 -0
- package/Map/MapImagePlot.d.ts +39 -0
- package/Map/MapImagePlot.js +138 -0
- package/Map/MapImagePlot.mjs +132 -0
- package/Map/MapShape.d.mts +2 -2
- package/Map/MapShape.d.ts +2 -2
- package/Map/MapShape.js +6 -6
- package/Map/MapShape.mjs +6 -6
- package/Map/MapShapePlot.d.mts +9 -1
- package/Map/MapShapePlot.d.ts +9 -1
- package/Map/MapShapePlot.js +17 -5
- package/Map/MapShapePlot.mjs +17 -5
- package/Map/index.d.mts +2 -3
- package/Map/index.d.ts +2 -3
- package/Map/index.js +11 -0
- package/Map/index.mjs +1 -0
- package/Map/reprojectEquirectangularImage.d.mts +60 -0
- package/Map/reprojectEquirectangularImage.d.ts +60 -0
- package/Map/reprojectEquirectangularImage.js +116 -0
- package/Map/reprojectEquirectangularImage.mjs +110 -0
- package/Map/seriesConfig/descriptionGetter.js +5 -1
- package/Map/seriesConfig/descriptionGetter.mjs +5 -1
- package/Map/seriesConfig/getColor.js +18 -6
- package/Map/seriesConfig/getColor.mjs +18 -6
- package/Map/seriesConfig/highlight.d.mts +10 -0
- package/Map/seriesConfig/highlight.d.ts +10 -0
- package/Map/seriesConfig/highlight.js +52 -0
- package/Map/seriesConfig/highlight.mjs +45 -0
- package/Map/seriesConfig/identifierCleaner.d.mts +3 -0
- package/Map/seriesConfig/identifierCleaner.d.ts +3 -0
- package/Map/seriesConfig/identifierCleaner.js +14 -0
- package/Map/seriesConfig/identifierCleaner.mjs +8 -0
- package/Map/seriesConfig/identifierSerializer.d.mts +3 -0
- package/Map/seriesConfig/identifierSerializer.d.ts +3 -0
- package/Map/seriesConfig/identifierSerializer.js +12 -0
- package/Map/seriesConfig/identifierSerializer.mjs +6 -0
- package/Map/seriesConfig/index.js +8 -6
- package/Map/seriesConfig/index.mjs +7 -5
- package/Map/seriesConfig/keyboardFocusHandler.d.mts +0 -6
- package/Map/seriesConfig/keyboardFocusHandler.d.ts +0 -6
- package/Map/seriesConfig/keyboardFocusHandler.js +40 -7
- package/Map/seriesConfig/keyboardFocusHandler.mjs +41 -8
- package/Map/seriesConfig/seriesProcessor.js +11 -2
- package/Map/seriesConfig/seriesProcessor.mjs +11 -2
- package/Map/seriesConfig/tooltip.js +8 -4
- package/Map/seriesConfig/tooltip.mjs +8 -4
- package/Map/seriesConfig/tooltipPosition.d.mts +8 -3
- package/Map/seriesConfig/tooltipPosition.d.ts +8 -3
- package/Map/seriesConfig/tooltipPosition.js +15 -27
- package/Map/seriesConfig/tooltipPosition.mjs +16 -27
- package/RadialBarChart/RadialBarElement.d.mts +1 -1
- package/RadialBarChart/RadialBarElement.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/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/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/ScatterChartPremium/webgl/ScatterWebGLProgram.d.mts +0 -2
- package/ScatterChartPremium/webgl/ScatterWebGLProgram.d.ts +0 -2
- package/ScatterChartPremium/webgl/ScatterWebGLProgram.js +23 -81
- package/ScatterChartPremium/webgl/ScatterWebGLProgram.mjs +23 -81
- package/index.js +1 -1
- package/index.mjs +1 -1
- package/internals/createGetVisibleCoordinate.d.mts +14 -0
- package/internals/createGetVisibleCoordinate.d.ts +14 -0
- package/internals/createGetVisibleCoordinate.js +66 -0
- package/internals/createGetVisibleCoordinate.mjs +60 -0
- 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/models/seriesType/mapShape.d.mts +2 -1
- package/models/seriesType/mapShape.d.ts +2 -1
- package/package.json +6 -6
- package/utils/webgl/glsl.d.mts +15 -0
- package/utils/webgl/glsl.d.ts +15 -0
- package/utils/webgl/glsl.js +34 -0
- package/utils/webgl/glsl.mjs +28 -0
- package/utils/webgl/instancedAttribute.d.mts +28 -0
- package/utils/webgl/instancedAttribute.d.ts +28 -0
- package/utils/webgl/instancedAttribute.js +57 -0
- package/utils/webgl/instancedAttribute.mjs +50 -0
- package/utils/webgl/utils.d.mts +21 -2
- package/utils/webgl/utils.d.ts +21 -2
- package/utils/webgl/utils.js +44 -8
- package/utils/webgl/utils.mjs +41 -7
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { usePinchGesture } from '@mui/x-charts-pro/internals';
|
|
4
|
+
import { selectorChartProjection } from "../../useGeoProjection/index.mjs";
|
|
5
|
+
import { getRotation, getTranslation } from "../mapZoom.utils.mjs";
|
|
6
|
+
export const useZoomOnPinch = ({
|
|
7
|
+
store,
|
|
8
|
+
instance
|
|
9
|
+
}, applyView, options) => {
|
|
10
|
+
const {
|
|
11
|
+
enabled,
|
|
12
|
+
rotationAllowed,
|
|
13
|
+
translationAllowed,
|
|
14
|
+
maxEmptySpace
|
|
15
|
+
} = options;
|
|
16
|
+
const projection = store.use(selectorChartProjection);
|
|
17
|
+
const clampZoomLevel = zoomLevel => Math.max(options.minZoomLevel, Math.min(options.maxZoomLevel, zoomLevel));
|
|
18
|
+
usePinchGesture(instance, {
|
|
19
|
+
enabled,
|
|
20
|
+
onPinch: (point, deltaScale) => {
|
|
21
|
+
if (!projection || !projection.invert) {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Same clamp-then-derive-factor flow as the wheel, so pinch obeys the identical bounds.
|
|
26
|
+
const currentZoom = store.state.geoProjectionZoom.zoomLevel ?? 1;
|
|
27
|
+
const nextZoom = clampZoomLevel(currentZoom * (1 + deltaScale));
|
|
28
|
+
const factor = nextZoom / currentZoom;
|
|
29
|
+
if (factor === 1) {
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
const geoPoint = projection.invert([point.x, point.y]);
|
|
33
|
+
if (!geoPoint) {
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
const nextRotation = getRotation(projection, geoPoint, [point.x, point.y], factor, rotationAllowed);
|
|
37
|
+
const scale = projection.scale();
|
|
38
|
+
const rotate = projection.rotate?.();
|
|
39
|
+
if (nextRotation) {
|
|
40
|
+
projection.rotate?.([-nextRotation[0], -nextRotation[1], nextRotation[2]]);
|
|
41
|
+
}
|
|
42
|
+
projection.scale(scale * factor);
|
|
43
|
+
const translation = getTranslation(store, projection, geoPoint, [point.x, point.y], translationAllowed, maxEmptySpace, store.state.geoProjectionZoom.translation ?? [0, 0]);
|
|
44
|
+
projection.rotate?.(rotate);
|
|
45
|
+
projection.scale(scale);
|
|
46
|
+
if (nextRotation || translation) {
|
|
47
|
+
applyView({
|
|
48
|
+
zoomLevel: nextZoom,
|
|
49
|
+
center: nextRotation ? [nextRotation[0], nextRotation[1]] : store.state.geoProjectionZoom.center ?? [0, 0],
|
|
50
|
+
translation: translation ?? store.state.geoProjectionZoom.translation ?? [0, 0],
|
|
51
|
+
roll: nextRotation ? nextRotation[2] : store.state.geoProjectionZoom.roll ?? 0
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { ChartPlugin } from '@mui/x-charts/internals';
|
|
2
|
+
import type { MapRotationAxis, MapTranslationAxis, MapZoomView, UseGeoProjectionZoomSignature } from "../useGeoProjectionZoom.types.mjs";
|
|
3
|
+
export declare const useZoomOnWheel: ({
|
|
4
|
+
store,
|
|
5
|
+
instance
|
|
6
|
+
}: Pick<Parameters<ChartPlugin<UseGeoProjectionZoomSignature>>[0], "store" | "instance">, applyView: (newView: MapZoomView) => void, options: {
|
|
7
|
+
enabled: boolean;
|
|
8
|
+
rotationAllowed: MapRotationAxis;
|
|
9
|
+
translationAllowed: MapTranslationAxis;
|
|
10
|
+
maxEmptySpace: number;
|
|
11
|
+
minZoomLevel: number;
|
|
12
|
+
maxZoomLevel: number;
|
|
13
|
+
}) => void;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { ChartPlugin } from '@mui/x-charts/internals';
|
|
2
|
+
import type { MapRotationAxis, MapTranslationAxis, MapZoomView, UseGeoProjectionZoomSignature } from "../useGeoProjectionZoom.types.js";
|
|
3
|
+
export declare const useZoomOnWheel: ({
|
|
4
|
+
store,
|
|
5
|
+
instance
|
|
6
|
+
}: Pick<Parameters<ChartPlugin<UseGeoProjectionZoomSignature>>[0], "store" | "instance">, applyView: (newView: MapZoomView) => void, options: {
|
|
7
|
+
enabled: boolean;
|
|
8
|
+
rotationAllowed: MapRotationAxis;
|
|
9
|
+
translationAllowed: MapTranslationAxis;
|
|
10
|
+
maxEmptySpace: number;
|
|
11
|
+
minZoomLevel: number;
|
|
12
|
+
maxZoomLevel: number;
|
|
13
|
+
}) => void;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
'use client';
|
|
3
|
+
|
|
4
|
+
Object.defineProperty(exports, "__esModule", {
|
|
5
|
+
value: true
|
|
6
|
+
});
|
|
7
|
+
exports.useZoomOnWheel = void 0;
|
|
8
|
+
var _internals = require("@mui/x-charts-pro/internals");
|
|
9
|
+
var _useGeoProjection = require("../../useGeoProjection");
|
|
10
|
+
var _mapZoom = require("../mapZoom.utils");
|
|
11
|
+
const useZoomOnWheel = ({
|
|
12
|
+
store,
|
|
13
|
+
instance
|
|
14
|
+
}, applyView, options) => {
|
|
15
|
+
const {
|
|
16
|
+
enabled,
|
|
17
|
+
rotationAllowed,
|
|
18
|
+
translationAllowed,
|
|
19
|
+
maxEmptySpace
|
|
20
|
+
} = options;
|
|
21
|
+
const projection = store.use(_useGeoProjection.selectorChartProjection);
|
|
22
|
+
const clampZoomLevel = zoomLevel => Math.max(options.minZoomLevel, Math.min(options.maxZoomLevel, zoomLevel));
|
|
23
|
+
(0, _internals.useWheelGesture)(instance, {
|
|
24
|
+
enabled,
|
|
25
|
+
onWheel: (point, event) => {
|
|
26
|
+
if (!projection || !projection.invert) {
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Clamp the target zoom first, then derive the factor actually applied. At the bounds the
|
|
31
|
+
// factor collapses to `1`, so wheeling further neither scales nor shifts the map.
|
|
32
|
+
const currentZoom = store.state.geoProjectionZoom.zoomLevel ?? 1;
|
|
33
|
+
const rawFactor = event.deltaY < 0 ? _mapZoom.WHEEL_ZOOM_STEP : 1 / _mapZoom.WHEEL_ZOOM_STEP;
|
|
34
|
+
const nextZoom = clampZoomLevel(currentZoom * rawFactor);
|
|
35
|
+
const factor = nextZoom / currentZoom;
|
|
36
|
+
if (factor === 1) {
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
const geoPoint = projection.invert([point.x, point.y]);
|
|
40
|
+
if (!geoPoint) {
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
const rotate = projection.rotate?.();
|
|
44
|
+
const scale = projection.scale();
|
|
45
|
+
const nextRotation = (0, _mapZoom.getRotation)(projection, geoPoint, [point.x, point.y], factor, rotationAllowed);
|
|
46
|
+
if (nextRotation) {
|
|
47
|
+
projection.rotate?.([-nextRotation[0], -nextRotation[1], nextRotation[2]]);
|
|
48
|
+
}
|
|
49
|
+
projection.scale(scale * factor);
|
|
50
|
+
const translation = (0, _mapZoom.getTranslation)(store, projection, geoPoint, [point.x, point.y], translationAllowed, maxEmptySpace);
|
|
51
|
+
projection.rotate?.(rotate);
|
|
52
|
+
projection.scale(scale);
|
|
53
|
+
if (nextRotation || translation) {
|
|
54
|
+
applyView({
|
|
55
|
+
zoomLevel: nextZoom,
|
|
56
|
+
center: nextRotation ? [nextRotation[0], nextRotation[1]] : store.state.geoProjectionZoom.center ?? [0, 0],
|
|
57
|
+
translation: translation ?? store.state.geoProjectionZoom.translation ?? [0, 0],
|
|
58
|
+
roll: nextRotation ? nextRotation[2] : store.state.geoProjectionZoom.roll ?? 0
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
};
|
|
64
|
+
exports.useZoomOnWheel = useZoomOnWheel;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { useWheelGesture } from '@mui/x-charts-pro/internals';
|
|
4
|
+
import { selectorChartProjection } from "../../useGeoProjection/index.mjs";
|
|
5
|
+
import { getRotation, getTranslation, WHEEL_ZOOM_STEP } from "../mapZoom.utils.mjs";
|
|
6
|
+
export const useZoomOnWheel = ({
|
|
7
|
+
store,
|
|
8
|
+
instance
|
|
9
|
+
}, applyView, options) => {
|
|
10
|
+
const {
|
|
11
|
+
enabled,
|
|
12
|
+
rotationAllowed,
|
|
13
|
+
translationAllowed,
|
|
14
|
+
maxEmptySpace
|
|
15
|
+
} = options;
|
|
16
|
+
const projection = store.use(selectorChartProjection);
|
|
17
|
+
const clampZoomLevel = zoomLevel => Math.max(options.minZoomLevel, Math.min(options.maxZoomLevel, zoomLevel));
|
|
18
|
+
useWheelGesture(instance, {
|
|
19
|
+
enabled,
|
|
20
|
+
onWheel: (point, event) => {
|
|
21
|
+
if (!projection || !projection.invert) {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Clamp the target zoom first, then derive the factor actually applied. At the bounds the
|
|
26
|
+
// factor collapses to `1`, so wheeling further neither scales nor shifts the map.
|
|
27
|
+
const currentZoom = store.state.geoProjectionZoom.zoomLevel ?? 1;
|
|
28
|
+
const rawFactor = event.deltaY < 0 ? WHEEL_ZOOM_STEP : 1 / WHEEL_ZOOM_STEP;
|
|
29
|
+
const nextZoom = clampZoomLevel(currentZoom * rawFactor);
|
|
30
|
+
const factor = nextZoom / currentZoom;
|
|
31
|
+
if (factor === 1) {
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
const geoPoint = projection.invert([point.x, point.y]);
|
|
35
|
+
if (!geoPoint) {
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
const rotate = projection.rotate?.();
|
|
39
|
+
const scale = projection.scale();
|
|
40
|
+
const nextRotation = getRotation(projection, geoPoint, [point.x, point.y], factor, rotationAllowed);
|
|
41
|
+
if (nextRotation) {
|
|
42
|
+
projection.rotate?.([-nextRotation[0], -nextRotation[1], nextRotation[2]]);
|
|
43
|
+
}
|
|
44
|
+
projection.scale(scale * factor);
|
|
45
|
+
const translation = getTranslation(store, projection, geoPoint, [point.x, point.y], translationAllowed, maxEmptySpace);
|
|
46
|
+
projection.rotate?.(rotate);
|
|
47
|
+
projection.scale(scale);
|
|
48
|
+
if (nextRotation || translation) {
|
|
49
|
+
applyView({
|
|
50
|
+
zoomLevel: nextZoom,
|
|
51
|
+
center: nextRotation ? [nextRotation[0], nextRotation[1]] : store.state.geoProjectionZoom.center ?? [0, 0],
|
|
52
|
+
translation: translation ?? store.state.geoProjectionZoom.translation ?? [0, 0],
|
|
53
|
+
roll: nextRotation ? nextRotation[2] : store.state.geoProjectionZoom.roll ?? 0
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
Object.defineProperty(exports, "useGeoProjectionZoom", {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
get: function () {
|
|
9
|
+
return _useGeoProjectionZoom.useGeoProjectionZoom;
|
|
10
|
+
}
|
|
11
|
+
});
|
|
12
|
+
var _useGeoProjectionZoom = require("./useGeoProjectionZoom");
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { useGeoProjectionZoom } from "./useGeoProjectionZoom.mjs";
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { GeoProjection } from '@mui/x-charts-vendor/d3-geo';
|
|
2
|
+
import type { ChartUsedStore } from '@mui/x-charts/internals';
|
|
3
|
+
import type { MapRotationAxis, MapTranslationAxis } from "./useGeoProjectionZoom.types.mjs";
|
|
4
|
+
import type { GeoProjectionInput } from "../useGeoProjection/index.mjs";
|
|
5
|
+
/** Multiplicative zoom step applied per wheel tick. */
|
|
6
|
+
export declare const WHEEL_ZOOM_STEP = 1.1;
|
|
7
|
+
/** Multiplicative zoom step applied per `zoomIn`/`zoomOut` call. */
|
|
8
|
+
export declare const BUTTON_ZOOM_STEP = 1.3;
|
|
9
|
+
type ProjectionFamily = 'azimuthal' | 'conic' | 'cylindrical' | 'albersUsa';
|
|
10
|
+
export declare function getProjectionFamily(projection: GeoProjectionInput | null): ProjectionFamily;
|
|
11
|
+
export declare function getDefaultMapInteraction(projection: GeoProjectionInput | null): {
|
|
12
|
+
rotationAllowed: MapRotationAxis;
|
|
13
|
+
translationAllowed: MapTranslationAxis;
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* For a given projection, apply a zoom factor to the scale and return the rotation that renders
|
|
17
|
+
* `geoPoint` at the `to` pixel coordinates, as `[longitude, latitude, roll]` (the view `center` plus
|
|
18
|
+
* the third d3 rotation angle).
|
|
19
|
+
*
|
|
20
|
+
* - With `rotationAllowed: 'both+roll'`, the roll is free to move but kept as stable as possible: the
|
|
21
|
+
* shortest-arc rotation dragging `geoPoint` onto `to` is composed with the current orientation, so
|
|
22
|
+
* the roll only drifts as much as strictly required.
|
|
23
|
+
* - With `rotationAllowed: 'both'`, both longitude and latitude are free but the roll is kept fixed at
|
|
24
|
+
* the current value.
|
|
25
|
+
* - With `rotationAllowed: 'longitude'`, only the longitude is solved; the latitude and roll are kept fixed.
|
|
26
|
+
* - With `rotationAllowed: 'none'`, `null` is returned so the caller keeps the current rotation.
|
|
27
|
+
*/
|
|
28
|
+
export declare function getRotation(projection: GeoProjection, geoPoint: [number, number], to: [number, number], zoomFactor?: number, rotationAllowed?: MapRotationAxis): [number, number, number] | null;
|
|
29
|
+
export declare function clampTranslationAxis(value: number, init: number, boundingBox0: number, boundingBox1: number, areaStart: number, areaEnd: number, gap: number): number;
|
|
30
|
+
export declare function getTranslation(store: ChartUsedStore<any>, projection: GeoProjection, geoPoint: [number, number], to: [number, number], translationAllowed?: MapTranslationAxis, maxEmptySpace?: number, currentTranslation?: [number, number]): [number, number] | null;
|
|
31
|
+
export {};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { GeoProjection } from '@mui/x-charts-vendor/d3-geo';
|
|
2
|
+
import type { ChartUsedStore } from '@mui/x-charts/internals';
|
|
3
|
+
import type { MapRotationAxis, MapTranslationAxis } from "./useGeoProjectionZoom.types.js";
|
|
4
|
+
import type { GeoProjectionInput } from "../useGeoProjection/index.js";
|
|
5
|
+
/** Multiplicative zoom step applied per wheel tick. */
|
|
6
|
+
export declare const WHEEL_ZOOM_STEP = 1.1;
|
|
7
|
+
/** Multiplicative zoom step applied per `zoomIn`/`zoomOut` call. */
|
|
8
|
+
export declare const BUTTON_ZOOM_STEP = 1.3;
|
|
9
|
+
type ProjectionFamily = 'azimuthal' | 'conic' | 'cylindrical' | 'albersUsa';
|
|
10
|
+
export declare function getProjectionFamily(projection: GeoProjectionInput | null): ProjectionFamily;
|
|
11
|
+
export declare function getDefaultMapInteraction(projection: GeoProjectionInput | null): {
|
|
12
|
+
rotationAllowed: MapRotationAxis;
|
|
13
|
+
translationAllowed: MapTranslationAxis;
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* For a given projection, apply a zoom factor to the scale and return the rotation that renders
|
|
17
|
+
* `geoPoint` at the `to` pixel coordinates, as `[longitude, latitude, roll]` (the view `center` plus
|
|
18
|
+
* the third d3 rotation angle).
|
|
19
|
+
*
|
|
20
|
+
* - With `rotationAllowed: 'both+roll'`, the roll is free to move but kept as stable as possible: the
|
|
21
|
+
* shortest-arc rotation dragging `geoPoint` onto `to` is composed with the current orientation, so
|
|
22
|
+
* the roll only drifts as much as strictly required.
|
|
23
|
+
* - With `rotationAllowed: 'both'`, both longitude and latitude are free but the roll is kept fixed at
|
|
24
|
+
* the current value.
|
|
25
|
+
* - With `rotationAllowed: 'longitude'`, only the longitude is solved; the latitude and roll are kept fixed.
|
|
26
|
+
* - With `rotationAllowed: 'none'`, `null` is returned so the caller keeps the current rotation.
|
|
27
|
+
*/
|
|
28
|
+
export declare function getRotation(projection: GeoProjection, geoPoint: [number, number], to: [number, number], zoomFactor?: number, rotationAllowed?: MapRotationAxis): [number, number, number] | null;
|
|
29
|
+
export declare function clampTranslationAxis(value: number, init: number, boundingBox0: number, boundingBox1: number, areaStart: number, areaEnd: number, gap: number): number;
|
|
30
|
+
export declare function getTranslation(store: ChartUsedStore<any>, projection: GeoProjection, geoPoint: [number, number], to: [number, number], translationAllowed?: MapTranslationAxis, maxEmptySpace?: number, currentTranslation?: [number, number]): [number, number] | null;
|
|
31
|
+
export {};
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.WHEEL_ZOOM_STEP = exports.BUTTON_ZOOM_STEP = void 0;
|
|
7
|
+
exports.clampTranslationAxis = clampTranslationAxis;
|
|
8
|
+
exports.getDefaultMapInteraction = getDefaultMapInteraction;
|
|
9
|
+
exports.getProjectionFamily = getProjectionFamily;
|
|
10
|
+
exports.getRotation = getRotation;
|
|
11
|
+
exports.getTranslation = getTranslation;
|
|
12
|
+
var _d3Geo = require("@mui/x-charts-vendor/d3-geo");
|
|
13
|
+
var _internals = require("@mui/x-charts/internals");
|
|
14
|
+
var _useGeoProjection = require("../useGeoProjection/useGeoProjection.selectors");
|
|
15
|
+
var _createGetVisibleCoordinate = require("../../createGetVisibleCoordinate");
|
|
16
|
+
var _rotationMath = require("./rotationMath");
|
|
17
|
+
/** Multiplicative zoom step applied per wheel tick. */
|
|
18
|
+
const WHEEL_ZOOM_STEP = exports.WHEEL_ZOOM_STEP = 1.1;
|
|
19
|
+
/** Multiplicative zoom step applied per `zoomIn`/`zoomOut` call. */
|
|
20
|
+
const BUTTON_ZOOM_STEP = exports.BUTTON_ZOOM_STEP = 1.3;
|
|
21
|
+
const PROJECTION_FAMILY = {
|
|
22
|
+
azimuthalEqualArea: 'azimuthal',
|
|
23
|
+
azimuthalEquidistant: 'azimuthal',
|
|
24
|
+
gnomonic: 'azimuthal',
|
|
25
|
+
orthographic: 'azimuthal',
|
|
26
|
+
stereographic: 'azimuthal',
|
|
27
|
+
conicConformal: 'conic',
|
|
28
|
+
conicEqualArea: 'conic',
|
|
29
|
+
conicEquidistant: 'conic',
|
|
30
|
+
albers: 'conic',
|
|
31
|
+
albersUsa: 'albersUsa',
|
|
32
|
+
equirectangular: 'cylindrical',
|
|
33
|
+
mercator: 'cylindrical',
|
|
34
|
+
transverseMercator: 'cylindrical',
|
|
35
|
+
equalEarth: 'cylindrical',
|
|
36
|
+
naturalEarth1: 'cylindrical'
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* The interaction that feels natural for each projection family, used as the default for
|
|
41
|
+
* `rotationAllowed`/`translationAllowed` when the consumer does not set them explicitly.
|
|
42
|
+
*/
|
|
43
|
+
const FAMILY_INTERACTION = {
|
|
44
|
+
azimuthal: {
|
|
45
|
+
rotationAllowed: 'both',
|
|
46
|
+
translationAllowed: 'none'
|
|
47
|
+
},
|
|
48
|
+
cylindrical: {
|
|
49
|
+
rotationAllowed: 'longitude',
|
|
50
|
+
translationAllowed: 'y'
|
|
51
|
+
},
|
|
52
|
+
conic: {
|
|
53
|
+
rotationAllowed: 'none',
|
|
54
|
+
translationAllowed: 'both'
|
|
55
|
+
},
|
|
56
|
+
albersUsa: {
|
|
57
|
+
rotationAllowed: 'none',
|
|
58
|
+
translationAllowed: 'both'
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
function getProjectionFamily(projection) {
|
|
62
|
+
if (projection == null) {
|
|
63
|
+
return 'cylindrical'; // fallback to avoid useless edge cases
|
|
64
|
+
}
|
|
65
|
+
if (typeof projection === 'string') {
|
|
66
|
+
return PROJECTION_FAMILY[projection] ?? 'cylindrical';
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Try to guess if users provided custom projection
|
|
70
|
+
|
|
71
|
+
// Conic projections expose the `parallels` accessor (e.g. conicConformal, albers).
|
|
72
|
+
if ('parallels' in projection) {
|
|
73
|
+
return 'conic';
|
|
74
|
+
}
|
|
75
|
+
// Composite projections such as `albersUsa` stitch several conics together and so drop `rotate`
|
|
76
|
+
// (there is no single sphere to spin). Treat them like the conic family they are built from.
|
|
77
|
+
if (typeof projection.rotate !== 'function') {
|
|
78
|
+
return 'conic';
|
|
79
|
+
}
|
|
80
|
+
// Azimuthal projections clip the sphere to a disc, so their clip angle sits strictly between 0 and
|
|
81
|
+
// 180° (e.g. 90° for orthographic). Flat projections leave it at 0° (no clipping).
|
|
82
|
+
const clipAngle = projection.clipAngle?.();
|
|
83
|
+
if (typeof clipAngle === 'number' && clipAngle > 0 && clipAngle < 180) {
|
|
84
|
+
return 'azimuthal';
|
|
85
|
+
}
|
|
86
|
+
return 'cylindrical';
|
|
87
|
+
}
|
|
88
|
+
function getDefaultMapInteraction(projection) {
|
|
89
|
+
return FAMILY_INTERACTION[getProjectionFamily(projection)];
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* For a given projection, apply a zoom factor to the scale and return the rotation that renders
|
|
94
|
+
* `geoPoint` at the `to` pixel coordinates, as `[longitude, latitude, roll]` (the view `center` plus
|
|
95
|
+
* the third d3 rotation angle).
|
|
96
|
+
*
|
|
97
|
+
* - With `rotationAllowed: 'both+roll'`, the roll is free to move but kept as stable as possible: the
|
|
98
|
+
* shortest-arc rotation dragging `geoPoint` onto `to` is composed with the current orientation, so
|
|
99
|
+
* the roll only drifts as much as strictly required.
|
|
100
|
+
* - With `rotationAllowed: 'both'`, both longitude and latitude are free but the roll is kept fixed at
|
|
101
|
+
* the current value.
|
|
102
|
+
* - With `rotationAllowed: 'longitude'`, only the longitude is solved; the latitude and roll are kept fixed.
|
|
103
|
+
* - With `rotationAllowed: 'none'`, `null` is returned so the caller keeps the current rotation.
|
|
104
|
+
*/
|
|
105
|
+
function getRotation(projection, geoPoint, to, zoomFactor = 1, rotationAllowed = 'both') {
|
|
106
|
+
if (!projection.invert || !projection.rotate) {
|
|
107
|
+
return null;
|
|
108
|
+
}
|
|
109
|
+
const rotate = projection.rotate?.();
|
|
110
|
+
const scale = projection.scale();
|
|
111
|
+
projection.scale(scale * zoomFactor);
|
|
112
|
+
projection.rotate?.([0, 0]);
|
|
113
|
+
const q = (0, _createGetVisibleCoordinate.createGetVisibleCoordinate)(projection)(to);
|
|
114
|
+
|
|
115
|
+
// Reset projection modifications to avoid side effects.
|
|
116
|
+
projection.rotate?.(rotate);
|
|
117
|
+
projection.scale(scale);
|
|
118
|
+
if (!geoPoint || !q) {
|
|
119
|
+
return null;
|
|
120
|
+
}
|
|
121
|
+
switch (rotationAllowed) {
|
|
122
|
+
case 'both+roll':
|
|
123
|
+
return (0, _rotationMath.getMinimalRollRotation)(rotate, geoPoint, q);
|
|
124
|
+
case 'both':
|
|
125
|
+
return (0, _rotationMath.getNoRollRotation)(rotate, geoPoint, q);
|
|
126
|
+
case 'longitude':
|
|
127
|
+
return (0, _rotationMath.getLongitudeRotation)(rotate, geoPoint, q);
|
|
128
|
+
case 'none':
|
|
129
|
+
default:
|
|
130
|
+
return null;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
function clampTranslationAxis(value, init, boundingBox0, boundingBox1, areaStart, areaEnd, gap) {
|
|
134
|
+
// Get min/mas translation allowed
|
|
135
|
+
const max = areaStart - boundingBox0 + init + gap;
|
|
136
|
+
const min = areaEnd - boundingBox1 + init - gap;
|
|
137
|
+
if (min > max) {
|
|
138
|
+
// If not translation accept the movement only if it reduces the gap
|
|
139
|
+
const prevGap0 = boundingBox0 - areaStart;
|
|
140
|
+
const prevGap1 = areaEnd - boundingBox1;
|
|
141
|
+
const gap = value - init;
|
|
142
|
+
const nextGap0 = boundingBox0 + gap - areaStart;
|
|
143
|
+
const nextGap1 = areaEnd - (boundingBox1 + gap);
|
|
144
|
+
if (Math.max(prevGap0, prevGap1) > Math.max(nextGap0, nextGap1)) {
|
|
145
|
+
return value;
|
|
146
|
+
}
|
|
147
|
+
return init;
|
|
148
|
+
}
|
|
149
|
+
return Math.min(max, Math.max(min, value));
|
|
150
|
+
}
|
|
151
|
+
function getTranslation(store, projection, geoPoint, to, translationAllowed = 'both', maxEmptySpace = 0, currentTranslation = [0, 0]) {
|
|
152
|
+
if (!projection.invert || translationAllowed === 'none') {
|
|
153
|
+
return null;
|
|
154
|
+
}
|
|
155
|
+
const q = (0, _createGetVisibleCoordinate.createGetVisibleCoordinate)(projection)(to);
|
|
156
|
+
if (!geoPoint || !q) {
|
|
157
|
+
return null;
|
|
158
|
+
}
|
|
159
|
+
const allowX = translationAllowed === 'both' || translationAllowed === 'x';
|
|
160
|
+
const allowY = translationAllowed === 'both' || translationAllowed === 'y';
|
|
161
|
+
const projectedGeoPoint = projection(geoPoint);
|
|
162
|
+
const projectedQ = projection(q);
|
|
163
|
+
if (!projectedGeoPoint || !projectedQ) {
|
|
164
|
+
return null;
|
|
165
|
+
}
|
|
166
|
+
const deltaX = projectedQ[0] - projectedGeoPoint[0];
|
|
167
|
+
const deltaY = projectedQ[1] - projectedGeoPoint[1];
|
|
168
|
+
const initTranslation = projection.translate();
|
|
169
|
+
const drawingArea = (0, _internals.selectorChartDrawingArea)(store.state);
|
|
170
|
+
let tx = currentTranslation[0];
|
|
171
|
+
let ty = currentTranslation[1];
|
|
172
|
+
|
|
173
|
+
// Clamp translation
|
|
174
|
+
const geoData = Number.isFinite(maxEmptySpace) ? (0, _useGeoProjection.selectorChartGeoData)(store.state) : null;
|
|
175
|
+
if (geoData) {
|
|
176
|
+
const [[bx0, by0], [bx1, by1]] = (0, _d3Geo.geoPath)(projection).bounds(geoData);
|
|
177
|
+
if (allowX) {
|
|
178
|
+
const translationX = clampTranslationAxis(initTranslation[0] + deltaX, initTranslation[0], bx0, bx1, drawingArea.left, drawingArea.left + drawingArea.width, maxEmptySpace * drawingArea.width);
|
|
179
|
+
tx = (translationX - drawingArea.left - drawingArea.width / 2) / drawingArea.width;
|
|
180
|
+
}
|
|
181
|
+
if (allowY) {
|
|
182
|
+
const translationY = clampTranslationAxis(initTranslation[1] + deltaY, initTranslation[1], by0, by1, drawingArea.top, drawingArea.top + drawingArea.height, maxEmptySpace * drawingArea.height);
|
|
183
|
+
ty = (translationY - drawingArea.top - drawingArea.height / 2) / drawingArea.height;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
return [tx, ty];
|
|
187
|
+
}
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
import { geoPath } from '@mui/x-charts-vendor/d3-geo';
|
|
2
|
+
import { selectorChartDrawingArea } from '@mui/x-charts/internals';
|
|
3
|
+
import { selectorChartGeoData } from "../useGeoProjection/useGeoProjection.selectors.mjs";
|
|
4
|
+
import { createGetVisibleCoordinate } from "../../createGetVisibleCoordinate.mjs";
|
|
5
|
+
import { getLongitudeRotation, getMinimalRollRotation, getNoRollRotation } from "./rotationMath.mjs";
|
|
6
|
+
|
|
7
|
+
/** Multiplicative zoom step applied per wheel tick. */
|
|
8
|
+
export const WHEEL_ZOOM_STEP = 1.1;
|
|
9
|
+
/** Multiplicative zoom step applied per `zoomIn`/`zoomOut` call. */
|
|
10
|
+
export const BUTTON_ZOOM_STEP = 1.3;
|
|
11
|
+
const PROJECTION_FAMILY = {
|
|
12
|
+
azimuthalEqualArea: 'azimuthal',
|
|
13
|
+
azimuthalEquidistant: 'azimuthal',
|
|
14
|
+
gnomonic: 'azimuthal',
|
|
15
|
+
orthographic: 'azimuthal',
|
|
16
|
+
stereographic: 'azimuthal',
|
|
17
|
+
conicConformal: 'conic',
|
|
18
|
+
conicEqualArea: 'conic',
|
|
19
|
+
conicEquidistant: 'conic',
|
|
20
|
+
albers: 'conic',
|
|
21
|
+
albersUsa: 'albersUsa',
|
|
22
|
+
equirectangular: 'cylindrical',
|
|
23
|
+
mercator: 'cylindrical',
|
|
24
|
+
transverseMercator: 'cylindrical',
|
|
25
|
+
equalEarth: 'cylindrical',
|
|
26
|
+
naturalEarth1: 'cylindrical'
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* The interaction that feels natural for each projection family, used as the default for
|
|
31
|
+
* `rotationAllowed`/`translationAllowed` when the consumer does not set them explicitly.
|
|
32
|
+
*/
|
|
33
|
+
const FAMILY_INTERACTION = {
|
|
34
|
+
azimuthal: {
|
|
35
|
+
rotationAllowed: 'both',
|
|
36
|
+
translationAllowed: 'none'
|
|
37
|
+
},
|
|
38
|
+
cylindrical: {
|
|
39
|
+
rotationAllowed: 'longitude',
|
|
40
|
+
translationAllowed: 'y'
|
|
41
|
+
},
|
|
42
|
+
conic: {
|
|
43
|
+
rotationAllowed: 'none',
|
|
44
|
+
translationAllowed: 'both'
|
|
45
|
+
},
|
|
46
|
+
albersUsa: {
|
|
47
|
+
rotationAllowed: 'none',
|
|
48
|
+
translationAllowed: 'both'
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
export function getProjectionFamily(projection) {
|
|
52
|
+
if (projection == null) {
|
|
53
|
+
return 'cylindrical'; // fallback to avoid useless edge cases
|
|
54
|
+
}
|
|
55
|
+
if (typeof projection === 'string') {
|
|
56
|
+
return PROJECTION_FAMILY[projection] ?? 'cylindrical';
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Try to guess if users provided custom projection
|
|
60
|
+
|
|
61
|
+
// Conic projections expose the `parallels` accessor (e.g. conicConformal, albers).
|
|
62
|
+
if ('parallels' in projection) {
|
|
63
|
+
return 'conic';
|
|
64
|
+
}
|
|
65
|
+
// Composite projections such as `albersUsa` stitch several conics together and so drop `rotate`
|
|
66
|
+
// (there is no single sphere to spin). Treat them like the conic family they are built from.
|
|
67
|
+
if (typeof projection.rotate !== 'function') {
|
|
68
|
+
return 'conic';
|
|
69
|
+
}
|
|
70
|
+
// Azimuthal projections clip the sphere to a disc, so their clip angle sits strictly between 0 and
|
|
71
|
+
// 180° (e.g. 90° for orthographic). Flat projections leave it at 0° (no clipping).
|
|
72
|
+
const clipAngle = projection.clipAngle?.();
|
|
73
|
+
if (typeof clipAngle === 'number' && clipAngle > 0 && clipAngle < 180) {
|
|
74
|
+
return 'azimuthal';
|
|
75
|
+
}
|
|
76
|
+
return 'cylindrical';
|
|
77
|
+
}
|
|
78
|
+
export function getDefaultMapInteraction(projection) {
|
|
79
|
+
return FAMILY_INTERACTION[getProjectionFamily(projection)];
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* For a given projection, apply a zoom factor to the scale and return the rotation that renders
|
|
84
|
+
* `geoPoint` at the `to` pixel coordinates, as `[longitude, latitude, roll]` (the view `center` plus
|
|
85
|
+
* the third d3 rotation angle).
|
|
86
|
+
*
|
|
87
|
+
* - With `rotationAllowed: 'both+roll'`, the roll is free to move but kept as stable as possible: the
|
|
88
|
+
* shortest-arc rotation dragging `geoPoint` onto `to` is composed with the current orientation, so
|
|
89
|
+
* the roll only drifts as much as strictly required.
|
|
90
|
+
* - With `rotationAllowed: 'both'`, both longitude and latitude are free but the roll is kept fixed at
|
|
91
|
+
* the current value.
|
|
92
|
+
* - With `rotationAllowed: 'longitude'`, only the longitude is solved; the latitude and roll are kept fixed.
|
|
93
|
+
* - With `rotationAllowed: 'none'`, `null` is returned so the caller keeps the current rotation.
|
|
94
|
+
*/
|
|
95
|
+
export function getRotation(projection, geoPoint, to, zoomFactor = 1, rotationAllowed = 'both') {
|
|
96
|
+
if (!projection.invert || !projection.rotate) {
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
99
|
+
const rotate = projection.rotate?.();
|
|
100
|
+
const scale = projection.scale();
|
|
101
|
+
projection.scale(scale * zoomFactor);
|
|
102
|
+
projection.rotate?.([0, 0]);
|
|
103
|
+
const q = createGetVisibleCoordinate(projection)(to);
|
|
104
|
+
|
|
105
|
+
// Reset projection modifications to avoid side effects.
|
|
106
|
+
projection.rotate?.(rotate);
|
|
107
|
+
projection.scale(scale);
|
|
108
|
+
if (!geoPoint || !q) {
|
|
109
|
+
return null;
|
|
110
|
+
}
|
|
111
|
+
switch (rotationAllowed) {
|
|
112
|
+
case 'both+roll':
|
|
113
|
+
return getMinimalRollRotation(rotate, geoPoint, q);
|
|
114
|
+
case 'both':
|
|
115
|
+
return getNoRollRotation(rotate, geoPoint, q);
|
|
116
|
+
case 'longitude':
|
|
117
|
+
return getLongitudeRotation(rotate, geoPoint, q);
|
|
118
|
+
case 'none':
|
|
119
|
+
default:
|
|
120
|
+
return null;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
export function clampTranslationAxis(value, init, boundingBox0, boundingBox1, areaStart, areaEnd, gap) {
|
|
124
|
+
// Get min/mas translation allowed
|
|
125
|
+
const max = areaStart - boundingBox0 + init + gap;
|
|
126
|
+
const min = areaEnd - boundingBox1 + init - gap;
|
|
127
|
+
if (min > max) {
|
|
128
|
+
// If not translation accept the movement only if it reduces the gap
|
|
129
|
+
const prevGap0 = boundingBox0 - areaStart;
|
|
130
|
+
const prevGap1 = areaEnd - boundingBox1;
|
|
131
|
+
const gap = value - init;
|
|
132
|
+
const nextGap0 = boundingBox0 + gap - areaStart;
|
|
133
|
+
const nextGap1 = areaEnd - (boundingBox1 + gap);
|
|
134
|
+
if (Math.max(prevGap0, prevGap1) > Math.max(nextGap0, nextGap1)) {
|
|
135
|
+
return value;
|
|
136
|
+
}
|
|
137
|
+
return init;
|
|
138
|
+
}
|
|
139
|
+
return Math.min(max, Math.max(min, value));
|
|
140
|
+
}
|
|
141
|
+
export function getTranslation(store, projection, geoPoint, to, translationAllowed = 'both', maxEmptySpace = 0, currentTranslation = [0, 0]) {
|
|
142
|
+
if (!projection.invert || translationAllowed === 'none') {
|
|
143
|
+
return null;
|
|
144
|
+
}
|
|
145
|
+
const q = createGetVisibleCoordinate(projection)(to);
|
|
146
|
+
if (!geoPoint || !q) {
|
|
147
|
+
return null;
|
|
148
|
+
}
|
|
149
|
+
const allowX = translationAllowed === 'both' || translationAllowed === 'x';
|
|
150
|
+
const allowY = translationAllowed === 'both' || translationAllowed === 'y';
|
|
151
|
+
const projectedGeoPoint = projection(geoPoint);
|
|
152
|
+
const projectedQ = projection(q);
|
|
153
|
+
if (!projectedGeoPoint || !projectedQ) {
|
|
154
|
+
return null;
|
|
155
|
+
}
|
|
156
|
+
const deltaX = projectedQ[0] - projectedGeoPoint[0];
|
|
157
|
+
const deltaY = projectedQ[1] - projectedGeoPoint[1];
|
|
158
|
+
const initTranslation = projection.translate();
|
|
159
|
+
const drawingArea = selectorChartDrawingArea(store.state);
|
|
160
|
+
let tx = currentTranslation[0];
|
|
161
|
+
let ty = currentTranslation[1];
|
|
162
|
+
|
|
163
|
+
// Clamp translation
|
|
164
|
+
const geoData = Number.isFinite(maxEmptySpace) ? selectorChartGeoData(store.state) : null;
|
|
165
|
+
if (geoData) {
|
|
166
|
+
const [[bx0, by0], [bx1, by1]] = geoPath(projection).bounds(geoData);
|
|
167
|
+
if (allowX) {
|
|
168
|
+
const translationX = clampTranslationAxis(initTranslation[0] + deltaX, initTranslation[0], bx0, bx1, drawingArea.left, drawingArea.left + drawingArea.width, maxEmptySpace * drawingArea.width);
|
|
169
|
+
tx = (translationX - drawingArea.left - drawingArea.width / 2) / drawingArea.width;
|
|
170
|
+
}
|
|
171
|
+
if (allowY) {
|
|
172
|
+
const translationY = clampTranslationAxis(initTranslation[1] + deltaY, initTranslation[1], by0, by1, drawingArea.top, drawingArea.top + drawingArea.height, maxEmptySpace * drawingArea.height);
|
|
173
|
+
ty = (translationY - drawingArea.top - drawingArea.height / 2) / drawingArea.height;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
return [tx, ty];
|
|
177
|
+
}
|