@deck.gl/widgets 9.3.0-beta.1 → 9.3.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.
@@ -2,8 +2,8 @@
2
2
  // SPDX-License-Identifier: MIT
3
3
  // Copyright (c) vis.gl contributors
4
4
 
5
- import {Widget, FlyToInterpolator, LinearInterpolator} from '@deck.gl/core';
6
- import type {WidgetProps, WidgetPlacement} from '@deck.gl/core';
5
+ import {Widget, FlyToInterpolator, LinearInterpolator, OrthographicView} from '@deck.gl/core';
6
+ import type {WidgetProps, WidgetPlacement, OrthographicViewState} from '@deck.gl/core';
7
7
  import {render} from 'preact';
8
8
  import {ButtonGroup} from './lib/components/button-group';
9
9
  import {IconButton} from './lib/components/icon-button';
@@ -21,6 +21,10 @@ export type ZoomWidgetProps = WidgetProps & {
21
21
  zoomOutLabel?: string;
22
22
  /** Zoom transition duration in ms. 0 disables the transition */
23
23
  transitionDuration?: number;
24
+ /** Which axes to apply zoom to. One of 'X', 'Y' or 'all'.
25
+ * Only effective if the current view is OrthographicView.
26
+ */
27
+ zoomAxis?: 'X' | 'Y' | 'all';
24
28
  /**
25
29
  * Callback when zoom buttons are clicked.
26
30
  * Called for each viewport that will be zoomed.
@@ -32,6 +36,10 @@ export type ZoomWidgetProps = WidgetProps & {
32
36
  delta: number;
33
37
  /** The new zoom level */
34
38
  zoom: number;
39
+ /** The new zoom level of the X axis, if using OrthographicView */
40
+ zoomX?: number;
41
+ /** The new zoom level of the Y axis, if using OrthographicView */
42
+ zoomY?: number;
35
43
  }) => void;
36
44
  };
37
45
 
@@ -44,6 +52,7 @@ export class ZoomWidget extends Widget<ZoomWidgetProps> {
44
52
  transitionDuration: 200,
45
53
  zoomInLabel: 'Zoom In',
46
54
  zoomOutLabel: 'Zoom Out',
55
+ zoomAxis: 'all',
47
56
  viewId: null,
48
57
  onZoom: () => {}
49
58
  };
@@ -80,25 +89,66 @@ export class ZoomWidget extends Widget<ZoomWidgetProps> {
80
89
  render(ui, rootElement);
81
90
  }
82
91
 
83
- handleZoom(viewId: string, nextZoom: number, delta: number) {
92
+ isOrthographicView(viewId: string): boolean {
93
+ const deck = this.deck;
94
+ const view = deck?.isInitialized && deck.getView(viewId);
95
+ return view instanceof OrthographicView;
96
+ }
97
+
98
+ handleZoom(viewId: string, delta: number) {
84
99
  // Respect minZoom/maxZoom constraints from the view state
85
100
  const viewState = this.getViewState(viewId);
86
- if (viewState) {
87
- const {minZoom, maxZoom} = viewState as any;
88
- if (Number.isFinite(minZoom)) {
89
- nextZoom = Math.max(minZoom, nextZoom);
90
- }
91
- if (Number.isFinite(maxZoom)) {
92
- nextZoom = Math.min(maxZoom, nextZoom);
101
+ const newViewState: Record<string, unknown> = {};
102
+
103
+ if (this.isOrthographicView(viewId)) {
104
+ const {zoomAxis} = this.props;
105
+ const {zoomX, minZoomX, maxZoomX, zoomY, minZoomY, maxZoomY} = normalizeOrthographicViewState(
106
+ viewState as any
107
+ );
108
+ let nextZoom: number;
109
+ let nextZoomY: number;
110
+ if (zoomAxis === 'X') {
111
+ nextZoom = clamp(zoomX + delta, minZoomX, maxZoomX);
112
+ nextZoomY = zoomY;
113
+ } else if (zoomAxis === 'Y') {
114
+ nextZoom = zoomX;
115
+ nextZoomY = clamp(zoomY + delta, minZoomY, maxZoomY);
116
+ } else {
117
+ const clampedDelta = clamp(
118
+ delta,
119
+ Math.max(minZoomX - zoomX, minZoomY - zoomY),
120
+ Math.min(maxZoomX - zoomX, maxZoomY - zoomY)
121
+ );
122
+ nextZoom = zoomX + clampedDelta;
123
+ nextZoomY = zoomY + clampedDelta;
93
124
  }
125
+ newViewState.zoom = [nextZoom, nextZoomY];
126
+ newViewState.zoomX = nextZoom;
127
+ newViewState.zoomY = nextZoomY;
128
+ // Call callback
129
+ this.props.onZoom?.({
130
+ viewId,
131
+ delta,
132
+ // `zoom` will not match the new state if using 2D zoom. Deprecated behavior for backward compatibility.
133
+ zoom: zoomAxis === 'Y' ? nextZoomY : nextZoom,
134
+ zoomX: nextZoom,
135
+ zoomY: nextZoomY
136
+ });
137
+ } else {
138
+ const {zoom = 0, minZoom, maxZoom} = viewState as any;
139
+ const nextZoom = clamp(zoom + delta, minZoom, maxZoom);
140
+ newViewState.zoom = nextZoom;
141
+ // Call callback
142
+ this.props.onZoom?.({
143
+ viewId,
144
+ delta,
145
+ zoom: nextZoom
146
+ });
94
147
  }
95
148
 
96
- // Call callback
97
- this.props.onZoom?.({viewId, delta, zoom: nextZoom});
98
-
99
149
  const nextViewState: Record<string, unknown> = {
100
150
  ...viewState,
101
- zoom: nextZoom
151
+ ...newViewState
102
152
  };
103
153
  if (this.props.transitionDuration > 0) {
104
154
  nextViewState.transitionDuration = this.props.transitionDuration;
@@ -106,7 +156,7 @@ export class ZoomWidget extends Widget<ZoomWidgetProps> {
106
156
  'latitude' in nextViewState
107
157
  ? new FlyToInterpolator()
108
158
  : new LinearInterpolator({
109
- transitionProps: ['zoom']
159
+ transitionProps: 'zoomX' in newViewState ? ['zoomX', 'zoomY'] : ['zoom']
110
160
  });
111
161
  }
112
162
  this.setViewState(viewId, nextViewState);
@@ -115,16 +165,41 @@ export class ZoomWidget extends Widget<ZoomWidgetProps> {
115
165
  handleZoomIn() {
116
166
  const viewIds = this.viewId ? [this.viewId] : (this.deck?.getViews().map(v => v.id) ?? []);
117
167
  for (const viewId of viewIds) {
118
- const viewState = this.getViewState(viewId);
119
- this.handleZoom(viewId, (viewState.zoom as number) + 1, 1);
168
+ this.handleZoom(viewId, 1);
120
169
  }
121
170
  }
122
171
 
123
172
  handleZoomOut() {
124
173
  const viewIds = this.viewId ? [this.viewId] : (this.deck?.getViews().map(v => v.id) ?? []);
125
174
  for (const viewId of viewIds) {
126
- const viewState = this.getViewState(viewId);
127
- this.handleZoom(viewId, (viewState.zoom as number) - 1, -1);
175
+ this.handleZoom(viewId, -1);
128
176
  }
129
177
  }
130
178
  }
179
+
180
+ function clamp(zoom: number, minZoom: number, maxZoom: number): number {
181
+ return zoom < minZoom ? minZoom : zoom > maxZoom ? maxZoom : zoom;
182
+ }
183
+
184
+ function normalizeOrthographicViewState({
185
+ zoom = 0,
186
+ zoomX,
187
+ zoomY,
188
+ minZoom = -Infinity,
189
+ maxZoom = Infinity,
190
+ minZoomX = minZoom,
191
+ maxZoomX = maxZoom,
192
+ minZoomY = minZoom,
193
+ maxZoomY = maxZoom
194
+ }: OrthographicViewState): {
195
+ zoomX: number;
196
+ zoomY: number;
197
+ minZoomX: number;
198
+ maxZoomX: number;
199
+ minZoomY: number;
200
+ maxZoomY: number;
201
+ } {
202
+ zoomX = zoomX ?? (Array.isArray(zoom) ? zoom[0] : zoom);
203
+ zoomY = zoomY ?? (Array.isArray(zoom) ? zoom[1] : zoom);
204
+ return {zoomX, zoomY, minZoomX, minZoomY, maxZoomX, maxZoomY};
205
+ }