@itwin/imodel-components-react 5.19.0 → 5.21.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/CHANGELOG.md +16 -0
- package/lib/imodel-components-react/UiIModelComponents.js +1 -1
- package/lib/imodel-components-react/UiIModelComponents.js.map +1 -1
- package/lib/imodel-components-react/color/AlphaSlider.js +100 -100
- package/lib/imodel-components-react/color/AlphaSlider.js.map +1 -1
- package/lib/imodel-components-react/editors/ColorEditor.js +20 -23
- package/lib/imodel-components-react/editors/ColorEditor.js.map +1 -1
- package/lib/imodel-components-react/editors/WeightEditor.js +21 -21
- package/lib/imodel-components-react/editors/WeightEditor.js.map +1 -1
- package/lib/imodel-components-react/inputs/new-editors/QuantityEditor.js +3 -2
- package/lib/imodel-components-react/inputs/new-editors/QuantityEditor.js.map +1 -1
- package/lib/imodel-components-react/inputs/new-editors/UseQuantityInfo.d.ts +2 -1
- package/lib/imodel-components-react/inputs/new-editors/UseQuantityInfo.d.ts.map +1 -1
- package/lib/imodel-components-react/inputs/new-editors/UseQuantityInfo.js +31 -11
- package/lib/imodel-components-react/inputs/new-editors/UseQuantityInfo.js.map +1 -1
- package/lib/imodel-components-react/lineweight/WeightPickerButton.js +53 -53
- package/lib/imodel-components-react/lineweight/WeightPickerButton.js.map +1 -1
- package/lib/imodel-components-react/navigationaids/Cube.js +1 -4
- package/lib/imodel-components-react/navigationaids/Cube.js.map +1 -1
- package/lib/imodel-components-react/navigationaids/CubeNavigationAid.js +296 -302
- package/lib/imodel-components-react/navigationaids/CubeNavigationAid.js.map +1 -1
- package/lib/imodel-components-react/navigationaids/DrawingNavigationAid.js +428 -425
- package/lib/imodel-components-react/navigationaids/DrawingNavigationAid.js.map +1 -1
- package/lib/imodel-components-react/timeline/BaseSolarDataProvider.js +20 -17
- package/lib/imodel-components-react/timeline/BaseSolarDataProvider.js.map +1 -1
- package/lib/imodel-components-react/timeline/BaseTimelineDataProvider.js +13 -10
- package/lib/imodel-components-react/timeline/BaseTimelineDataProvider.js.map +1 -1
- package/lib/imodel-components-react/timeline/InlineEdit.js +20 -20
- package/lib/imodel-components-react/timeline/InlineEdit.js.map +1 -1
- package/lib/imodel-components-react/timeline/SolarTimeline.js +144 -144
- package/lib/imodel-components-react/timeline/SolarTimeline.js.map +1 -1
- package/lib/imodel-components-react/viewport/ViewportComponentEvents.js +16 -15
- package/lib/imodel-components-react/viewport/ViewportComponentEvents.js.map +1 -1
- package/package.json +7 -7
|
@@ -30,384 +30,21 @@ export var MapMode;
|
|
|
30
30
|
* @public
|
|
31
31
|
*/
|
|
32
32
|
export class DrawingNavigationAid extends React.Component {
|
|
33
|
+
_rootElement = React.createRef();
|
|
34
|
+
_viewContainerElement = React.createRef();
|
|
35
|
+
_viewElement = React.createRef();
|
|
36
|
+
_rootOffset = DOMRect.fromRect({
|
|
37
|
+
x: 0,
|
|
38
|
+
y: 0,
|
|
39
|
+
width: 0,
|
|
40
|
+
height: 0,
|
|
41
|
+
});
|
|
42
|
+
_viewport;
|
|
43
|
+
_animationFrame;
|
|
44
|
+
_mounted = false;
|
|
45
|
+
state;
|
|
33
46
|
constructor(props) {
|
|
34
47
|
super(props);
|
|
35
|
-
this._rootElement = React.createRef();
|
|
36
|
-
this._viewContainerElement = React.createRef();
|
|
37
|
-
this._viewElement = React.createRef();
|
|
38
|
-
this._rootOffset = DOMRect.fromRect({
|
|
39
|
-
x: 0,
|
|
40
|
-
y: 0,
|
|
41
|
-
width: 0,
|
|
42
|
-
height: 0,
|
|
43
|
-
});
|
|
44
|
-
this._mounted = false;
|
|
45
|
-
this._isViewport3D = () => {
|
|
46
|
-
return this.state.view !== undefined && this.state.view.is3d();
|
|
47
|
-
};
|
|
48
|
-
this._animation = () => {
|
|
49
|
-
const t = Date.now();
|
|
50
|
-
const delta = this._lastTime ? t - this._lastTime : 16;
|
|
51
|
-
this._lastTime = t;
|
|
52
|
-
if (this.state.animation !== 1) {
|
|
53
|
-
const animation = Math.min(1, this.state.animation +
|
|
54
|
-
delta / (1000 * (this.props.animationTime || 0.4)));
|
|
55
|
-
this._updateFrustum();
|
|
56
|
-
if (this._mounted) {
|
|
57
|
-
this.setState({ animation }, () => {
|
|
58
|
-
this._animationFrame = setTimeout(this._animation, 16.667);
|
|
59
|
-
});
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
else {
|
|
63
|
-
this._lastTime = undefined;
|
|
64
|
-
this._animationEnd();
|
|
65
|
-
}
|
|
66
|
-
};
|
|
67
|
-
this._animationEnd = () => {
|
|
68
|
-
const hasViewportMoved = !this.state.origin.isAlmostEqual(this.state.startOrigin) ||
|
|
69
|
-
!this.state.rotation.isAlmostEqual(this.state.startRotation);
|
|
70
|
-
const startMapOrigin = Point3d.createFrom(this.state.mapOrigin);
|
|
71
|
-
const startMapExtents = Vector3d.createFrom(this.state.mapExtents);
|
|
72
|
-
const startDrawingZoom = this.state.drawingZoom;
|
|
73
|
-
const startOrigin = this.state.origin;
|
|
74
|
-
const startRotation = this.state.rotation;
|
|
75
|
-
if (this._mounted) {
|
|
76
|
-
this.setState({
|
|
77
|
-
startMapOrigin,
|
|
78
|
-
startDrawingZoom,
|
|
79
|
-
startOrigin,
|
|
80
|
-
startRotation,
|
|
81
|
-
startMapExtents,
|
|
82
|
-
}, () => {
|
|
83
|
-
if (this.props.onAnimationEnd)
|
|
84
|
-
this.props.onAnimationEnd();
|
|
85
|
-
if (hasViewportMoved)
|
|
86
|
-
this._updateFrustum(true);
|
|
87
|
-
});
|
|
88
|
-
}
|
|
89
|
-
};
|
|
90
|
-
this._panAnimation = () => {
|
|
91
|
-
const t = Date.now();
|
|
92
|
-
if (this._lastPanTime === undefined)
|
|
93
|
-
this._lastPanTime = t - 16.667;
|
|
94
|
-
const delta = t - this._lastPanTime;
|
|
95
|
-
this._lastPanTime = t;
|
|
96
|
-
if (!this.state.panningDirection.isAlmostZero && this.state.isMoving) {
|
|
97
|
-
const { panningDirection } = this.state;
|
|
98
|
-
const offset = panningDirection.scale(delta / 1000 / this.state.drawingZoom);
|
|
99
|
-
const mapOrigin = this.state.mapOrigin.plus(offset);
|
|
100
|
-
const origin = this.state.origin.plus(offset);
|
|
101
|
-
this._updateFrustum();
|
|
102
|
-
if (this._mounted) {
|
|
103
|
-
this.setState({ mapOrigin, origin, panningDirection }, () => {
|
|
104
|
-
this._animationFrame = setTimeout(this._panAnimation, 16.667);
|
|
105
|
-
});
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
else {
|
|
109
|
-
this._lastPanTime = undefined;
|
|
110
|
-
this._updateFrustum(true);
|
|
111
|
-
}
|
|
112
|
-
};
|
|
113
|
-
// Synchronize with rotation coming from the Viewport
|
|
114
|
-
this._handleViewRotationChangeEvent = (args) => {
|
|
115
|
-
if (!this.state.isMoving &&
|
|
116
|
-
!this.state.isPanning &&
|
|
117
|
-
this.props.viewport === args.viewport) {
|
|
118
|
-
const extents = args.viewport.view.getExtents().clone();
|
|
119
|
-
const rotation = args.viewport.view.getRotation().clone();
|
|
120
|
-
const halfExtents = extents.scale(0.5);
|
|
121
|
-
const offset = this.state.rotateMinimapWithView || this._isViewport3D()
|
|
122
|
-
? rotation.multiplyTransposeVector(halfExtents)
|
|
123
|
-
: halfExtents;
|
|
124
|
-
const origin = args.viewport.view.getOrigin().plus(offset);
|
|
125
|
-
const deltaZoom = (this.state.extents.x - extents.x) / this.state.extents.x;
|
|
126
|
-
let drawingZoom = this.state.drawingZoom / (1 - deltaZoom);
|
|
127
|
-
const deltaOrigin = origin.minus(this.state.origin);
|
|
128
|
-
let mapOrigin = this.state.mapOrigin.plus(deltaOrigin);
|
|
129
|
-
mapOrigin = mapOrigin.plus(Vector3d.createFrom(origin.minus(mapOrigin)).scale(deltaZoom));
|
|
130
|
-
if (this.state.viewId !== args.viewport.view.id) {
|
|
131
|
-
const rect = this.state.rotateMinimapWithView || this._isViewport3D()
|
|
132
|
-
? extents
|
|
133
|
-
: DrawingNavigationAid.findRotatedWindowDimensions(extents, rotation);
|
|
134
|
-
const maxRectDim = Math.max(rect.y, rect.x);
|
|
135
|
-
const maxExtentDim = Math.max(this.state.mapExtents.x, this.state.mapExtents.y);
|
|
136
|
-
drawingZoom = maxExtentDim / (3 * maxRectDim);
|
|
137
|
-
mapOrigin = origin.clone();
|
|
138
|
-
this._viewport = args.viewport;
|
|
139
|
-
this.setState({
|
|
140
|
-
viewId: args.viewport.view.id,
|
|
141
|
-
view: args.viewport.view.clone(),
|
|
142
|
-
});
|
|
143
|
-
}
|
|
144
|
-
if (this._mounted) {
|
|
145
|
-
this.setState({
|
|
146
|
-
startOrigin: origin,
|
|
147
|
-
origin,
|
|
148
|
-
extents,
|
|
149
|
-
startRotation: rotation,
|
|
150
|
-
rotation,
|
|
151
|
-
startMapOrigin: mapOrigin,
|
|
152
|
-
mapOrigin,
|
|
153
|
-
startDrawingZoom: drawingZoom,
|
|
154
|
-
drawingZoom,
|
|
155
|
-
});
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
};
|
|
159
|
-
this._updateFrustum = (complete = false) => {
|
|
160
|
-
const halfExtents = this.state.extents.scale(0.5);
|
|
161
|
-
const offset = this.state.rotateMinimapWithView || this._isViewport3D()
|
|
162
|
-
? this.state.rotation.multiplyTransposeVector(halfExtents)
|
|
163
|
-
: halfExtents;
|
|
164
|
-
const origin = this.state.origin.minus(offset);
|
|
165
|
-
ViewportComponentEvents.setDrawingViewportState(origin, this.state.rotation, complete);
|
|
166
|
-
};
|
|
167
|
-
this._toggleRotationMode = () => {
|
|
168
|
-
const rotateMinimapWithView = !this.state.rotateMinimapWithView;
|
|
169
|
-
this.setState({ rotateMinimapWithView }, () => {
|
|
170
|
-
if (this._viewport)
|
|
171
|
-
this._handleViewRotationChangeEvent({ viewport: this._viewport });
|
|
172
|
-
});
|
|
173
|
-
};
|
|
174
|
-
this._handleKeyUp = (event) => {
|
|
175
|
-
if (event.key === Key.Escape.valueOf() &&
|
|
176
|
-
this.state.mode === MapMode.Opened) {
|
|
177
|
-
this._closeLargeMap();
|
|
178
|
-
}
|
|
179
|
-
};
|
|
180
|
-
this._lastClientXY = Point2d.createZero();
|
|
181
|
-
this._handleMouseDown = (event) => {
|
|
182
|
-
// Used only to determine if mouse was moved between mousedown and mouseup
|
|
183
|
-
const mouseStart = Point2d.create(event.clientX, event.clientY);
|
|
184
|
-
this.setState({ mouseStart });
|
|
185
|
-
this._lastClientXY = Point2d.create(event.clientX, event.clientY);
|
|
186
|
-
};
|
|
187
|
-
this._handleDrawingMouseDown = (event) => {
|
|
188
|
-
if (this.state.mode === MapMode.Opened) {
|
|
189
|
-
event.preventDefault();
|
|
190
|
-
this.setState({ isPanning: true });
|
|
191
|
-
}
|
|
192
|
-
};
|
|
193
|
-
this._handleWindowMouseDown = (event) => {
|
|
194
|
-
event.preventDefault();
|
|
195
|
-
this.setState({ isMoving: true });
|
|
196
|
-
};
|
|
197
|
-
this._handleMouseDrag = (event) => {
|
|
198
|
-
const mouse = Point2d.create(event.clientX, event.clientY);
|
|
199
|
-
const movement = mouse.minus(this._lastClientXY);
|
|
200
|
-
if (this.state.isMoving) {
|
|
201
|
-
// add scaled mouse movement
|
|
202
|
-
this._processWindowDrag(movement);
|
|
203
|
-
}
|
|
204
|
-
else {
|
|
205
|
-
if (this.state.isPanning && this.state.mode === MapMode.Opened) {
|
|
206
|
-
const vect = Vector3d.create(movement.x / this.state.drawingZoom, -movement.y / this.state.drawingZoom, 0);
|
|
207
|
-
const offset = this.state.rotateMinimapWithView || this._isViewport3D()
|
|
208
|
-
? this.state.rotation.multiplyTransposeVector(vect)
|
|
209
|
-
: vect;
|
|
210
|
-
const mapOrigin = this.state.mapOrigin.minus(offset);
|
|
211
|
-
this.setState({ startMapOrigin: mapOrigin, mapOrigin });
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
this._lastClientXY = mouse;
|
|
215
|
-
};
|
|
216
|
-
this._handleMouseDragEnd = (event) => {
|
|
217
|
-
const mouse = Point2d.create(event.clientX, event.clientY);
|
|
218
|
-
if (mouse.isAlmostEqual(this.state.mouseStart) &&
|
|
219
|
-
this.state.mode === MapMode.Closed &&
|
|
220
|
-
(event.target === this._viewContainerElement.current ||
|
|
221
|
-
event.target === this._viewElement.current)) {
|
|
222
|
-
this._openLargeMap();
|
|
223
|
-
}
|
|
224
|
-
else if (this.state.isMoving) {
|
|
225
|
-
this._processWindowEndDrag();
|
|
226
|
-
}
|
|
227
|
-
else if (this.state.isPanning) {
|
|
228
|
-
if (this.state.mode === MapMode.Opened) {
|
|
229
|
-
event.stopPropagation();
|
|
230
|
-
this.setState({ isPanning: false });
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
else if ((!(event.target instanceof Node) ||
|
|
234
|
-
(this._rootElement.current &&
|
|
235
|
-
!this._rootElement.current.contains(event.target))) &&
|
|
236
|
-
mouse.isAlmostEqual(this.state.mouseStart)) {
|
|
237
|
-
this._closeLargeMap();
|
|
238
|
-
}
|
|
239
|
-
this._lastClientXY = Point2d.create(event.clientX, event.clientY);
|
|
240
|
-
};
|
|
241
|
-
this._handleWindowTouchStart = (event) => {
|
|
242
|
-
if (1 !== event.targetTouches.length)
|
|
243
|
-
return;
|
|
244
|
-
window.addEventListener("touchmove", this._onTouchMove, false);
|
|
245
|
-
window.addEventListener("touchend", this._onTouchEnd, false);
|
|
246
|
-
const mouseStart = Point2d.create(event.targetTouches[0].clientX, event.targetTouches[0].clientY);
|
|
247
|
-
this.setState({ mouseStart });
|
|
248
|
-
this._lastClientXY = mouseStart.clone();
|
|
249
|
-
this.setState({ isMoving: true });
|
|
250
|
-
};
|
|
251
|
-
this._onTouchMove = (event) => {
|
|
252
|
-
if (1 !== event.targetTouches.length)
|
|
253
|
-
return;
|
|
254
|
-
const mouse = Point2d.create(event.targetTouches[0].clientX, event.targetTouches[0].clientY);
|
|
255
|
-
const movement = mouse.minus(this._lastClientXY);
|
|
256
|
-
// add scaled mouse movement
|
|
257
|
-
this._processWindowDrag(movement);
|
|
258
|
-
this._lastClientXY = mouse;
|
|
259
|
-
};
|
|
260
|
-
this._onTouchEnd = (event) => {
|
|
261
|
-
if (0 !== event.targetTouches.length)
|
|
262
|
-
return;
|
|
263
|
-
this._processWindowEndDrag();
|
|
264
|
-
if (0 !== event.changedTouches.length)
|
|
265
|
-
this._lastClientXY = Point2d.create(event.changedTouches[0].clientX, event.changedTouches[0].clientY); // Doesn't seem necessary...but _handleMouseDragEnd sets it...
|
|
266
|
-
window.removeEventListener("touchmove", this._onTouchMove);
|
|
267
|
-
window.removeEventListener("touchend", this._onTouchEnd);
|
|
268
|
-
};
|
|
269
|
-
this._getClosedMapSize = () => {
|
|
270
|
-
if (this.props.closeSize === undefined)
|
|
271
|
-
return DrawingNavigationAid.getDefaultClosedMapSize();
|
|
272
|
-
return this.props.closeSize;
|
|
273
|
-
};
|
|
274
|
-
this._getOpenedMapSize = () => {
|
|
275
|
-
if (this.props.openSize === undefined)
|
|
276
|
-
return DrawingNavigationAid.getDefaultOpenedMapSize(this._rootOffset.right, this._rootOffset.top);
|
|
277
|
-
return this.props.openSize;
|
|
278
|
-
};
|
|
279
|
-
this._openLargeMap = () => {
|
|
280
|
-
if (this.state.mode === MapMode.Closed && this.state.animation === 1.0) {
|
|
281
|
-
if (this._rootElement.current) {
|
|
282
|
-
const rect = this._rootElement.current.getBoundingClientRect();
|
|
283
|
-
this._rootOffset = rect;
|
|
284
|
-
}
|
|
285
|
-
const startMapExtents = Vector3d.createFrom(this.state.mapExtents);
|
|
286
|
-
const mapExtents = this._getOpenedMapSize();
|
|
287
|
-
this.setState({
|
|
288
|
-
mode: MapMode.Opened,
|
|
289
|
-
isMoving: false,
|
|
290
|
-
isPanning: false,
|
|
291
|
-
mapExtents,
|
|
292
|
-
startMapExtents,
|
|
293
|
-
animation: 0,
|
|
294
|
-
}, () => {
|
|
295
|
-
this._animationFrame = setTimeout(this._animation);
|
|
296
|
-
});
|
|
297
|
-
}
|
|
298
|
-
};
|
|
299
|
-
this._closeLargeMap = () => {
|
|
300
|
-
if (this.state.mode === MapMode.Opened && this.state.animation === 1.0) {
|
|
301
|
-
const startMapOrigin = this.state.mapOrigin;
|
|
302
|
-
const mapOrigin = this.state.origin.clone();
|
|
303
|
-
const startMapExtents = Vector3d.createFrom(this.state.mapExtents);
|
|
304
|
-
const mapExtents = this._getClosedMapSize();
|
|
305
|
-
const rect = this.state.rotateMinimapWithView || this._isViewport3D()
|
|
306
|
-
? this.state.extents
|
|
307
|
-
: DrawingNavigationAid.findRotatedWindowDimensions(this.state.extents, this.state.rotation);
|
|
308
|
-
const maxRectDim = Math.max(rect.y, rect.x);
|
|
309
|
-
const maxExtentDim = Math.max(mapExtents.x, mapExtents.y);
|
|
310
|
-
const drawingZoom = maxExtentDim / (3 * maxRectDim);
|
|
311
|
-
const startDrawingZoom = this.state.drawingZoom;
|
|
312
|
-
this.setState({
|
|
313
|
-
mode: MapMode.Closed,
|
|
314
|
-
startMapOrigin,
|
|
315
|
-
mapOrigin,
|
|
316
|
-
startDrawingZoom,
|
|
317
|
-
drawingZoom,
|
|
318
|
-
isMoving: false,
|
|
319
|
-
isPanning: false,
|
|
320
|
-
startMapExtents,
|
|
321
|
-
mapExtents,
|
|
322
|
-
panningDirection: Vector3d.createZero(),
|
|
323
|
-
animation: 0,
|
|
324
|
-
}, () => {
|
|
325
|
-
this._animationFrame = setTimeout(this._animation, 16.667);
|
|
326
|
-
});
|
|
327
|
-
}
|
|
328
|
-
};
|
|
329
|
-
this._getPanVector = () => {
|
|
330
|
-
const is3D = this._isViewport3D();
|
|
331
|
-
const rect = this.state.rotateMinimapWithView || is3D
|
|
332
|
-
? this.state.extents
|
|
333
|
-
: DrawingNavigationAid.findRotatedWindowDimensions(this.state.extents, this.state.rotation);
|
|
334
|
-
const mapExtents = this.state.mapExtents.scale(1 / this.state.drawingZoom);
|
|
335
|
-
const maxMagnitude = 80; // maximum acceleration
|
|
336
|
-
const magnitudeTravel = 30; // How far, in pixels, that magnitude increases from 0 to max acceleration
|
|
337
|
-
const diff = Vector3d.createFrom(this.state.origin.minus(this.state.mapOrigin));
|
|
338
|
-
const diffVector = this.state.rotateMinimapWithView || is3D
|
|
339
|
-
? this.state.rotation.multiplyVector(diff)
|
|
340
|
-
: diff;
|
|
341
|
-
// capture any values
|
|
342
|
-
const magnitudeVector = Vector3d.create(Math.max(0, Math.abs(diffVector.x) - (mapExtents.x - rect.x) / 2), Math.max(0, Math.abs(diffVector.y) - (mapExtents.y - rect.y) / 2));
|
|
343
|
-
if (magnitudeVector.isAlmostZero)
|
|
344
|
-
return Vector3d.createZero();
|
|
345
|
-
const magnitude = (Math.min(magnitudeVector.magnitude() * this.state.drawingZoom, magnitudeTravel) /
|
|
346
|
-
magnitudeTravel) *
|
|
347
|
-
maxMagnitude;
|
|
348
|
-
const vect = Vector3d.createFrom(this.state.origin.minus(this.state.mapOrigin)); // vect will never be zero or magnitude would also be zero
|
|
349
|
-
const norm = vect.normalize();
|
|
350
|
-
return norm.scale(magnitude); // norm is only undefined when vect is zero, in which it would have returned at magnitudeVector.isAlmostZero
|
|
351
|
-
};
|
|
352
|
-
this._handleWheel = (event) => {
|
|
353
|
-
if (this.state.mode === MapMode.Opened && this.state.animation === 1) {
|
|
354
|
-
const { mapOrigin, drawingZoom } = this.state;
|
|
355
|
-
const mapSize = this._getOpenedMapSize();
|
|
356
|
-
const mouseX = event.clientX - this._rootOffset.right + mapSize.x / 2;
|
|
357
|
-
const mouseY = event.clientY - this._rootOffset.top - mapSize.y / 2;
|
|
358
|
-
const is3D = this._isViewport3D();
|
|
359
|
-
if (event.deltaY < 0) {
|
|
360
|
-
const zoom = drawingZoom * 1.1;
|
|
361
|
-
const vect = Vector3d.create((mouseX * 0.1) / zoom, (-mouseY * 0.1) / zoom, 0);
|
|
362
|
-
const offset = this.state.rotateMinimapWithView || is3D
|
|
363
|
-
? this.state.rotation.multiplyTransposeVector(vect)
|
|
364
|
-
: vect;
|
|
365
|
-
const m = mapOrigin.plus(offset);
|
|
366
|
-
this.setState({ mapOrigin: m, drawingZoom: zoom });
|
|
367
|
-
}
|
|
368
|
-
if (event.deltaY > 0) {
|
|
369
|
-
const zoom = drawingZoom / 1.1;
|
|
370
|
-
const vect = Vector3d.create((mouseX * 0.1) / drawingZoom, (-mouseY * 0.1) / drawingZoom, 0);
|
|
371
|
-
const offset = this.state.rotateMinimapWithView || is3D
|
|
372
|
-
? this.state.rotation.multiplyTransposeVector(vect)
|
|
373
|
-
: vect;
|
|
374
|
-
const m = mapOrigin.minus(offset);
|
|
375
|
-
this.setState({ mapOrigin: m, drawingZoom: zoom });
|
|
376
|
-
}
|
|
377
|
-
}
|
|
378
|
-
};
|
|
379
|
-
this._handleZoomIn = () => {
|
|
380
|
-
const zoom = this.state.drawingZoom * 1.4;
|
|
381
|
-
this.setState({ drawingZoom: zoom });
|
|
382
|
-
};
|
|
383
|
-
this._handleZoomOut = () => {
|
|
384
|
-
const zoom = this.state.drawingZoom / 1.4;
|
|
385
|
-
this.setState({ drawingZoom: zoom });
|
|
386
|
-
};
|
|
387
|
-
this._handleUnrotate = () => {
|
|
388
|
-
const startRotation = this.state.rotation;
|
|
389
|
-
const halfExtents = this.state.extents.scale(0.5);
|
|
390
|
-
const offset = this.state.rotateMinimapWithView || this._isViewport3D()
|
|
391
|
-
? Vector3d.createZero()
|
|
392
|
-
: this.state.rotation
|
|
393
|
-
.multiplyTransposeVector(halfExtents)
|
|
394
|
-
.minus(halfExtents);
|
|
395
|
-
const startOrigin = this.state.origin;
|
|
396
|
-
const origin = this.state.origin.plus(offset);
|
|
397
|
-
const startMapOrigin = this.state.mapOrigin;
|
|
398
|
-
const mapOrigin = this.state.mapOrigin.plus(offset);
|
|
399
|
-
this.setState({
|
|
400
|
-
animation: 0,
|
|
401
|
-
startOrigin,
|
|
402
|
-
origin,
|
|
403
|
-
startMapOrigin,
|
|
404
|
-
mapOrigin,
|
|
405
|
-
startRotation,
|
|
406
|
-
rotation: Matrix3d.createIdentity(),
|
|
407
|
-
}, () => {
|
|
408
|
-
this._animationFrame = setTimeout(this._animation, 16.667);
|
|
409
|
-
});
|
|
410
|
-
};
|
|
411
48
|
const mode = props.initialMapMode || MapMode.Closed;
|
|
412
49
|
const mapExtents = mode === MapMode.Closed
|
|
413
50
|
? this._getClosedMapSize()
|
|
@@ -527,6 +164,77 @@ export class DrawingNavigationAid extends React.Component {
|
|
|
527
164
|
return ReactDOM.createPortal(nodes, drawingPortal);
|
|
528
165
|
}
|
|
529
166
|
}
|
|
167
|
+
_isViewport3D = () => {
|
|
168
|
+
return this.state.view !== undefined && this.state.view.is3d();
|
|
169
|
+
};
|
|
170
|
+
_lastTime;
|
|
171
|
+
static _animationFn = (t) => t < 0.5 ? 2 * t ** 2 : -1 + (4 - 2 * t) * t;
|
|
172
|
+
_animation = () => {
|
|
173
|
+
const t = Date.now();
|
|
174
|
+
const delta = this._lastTime ? t - this._lastTime : 16;
|
|
175
|
+
this._lastTime = t;
|
|
176
|
+
if (this.state.animation !== 1) {
|
|
177
|
+
const animation = Math.min(1, this.state.animation +
|
|
178
|
+
delta / (1000 * (this.props.animationTime || 0.4)));
|
|
179
|
+
this._updateFrustum();
|
|
180
|
+
if (this._mounted) {
|
|
181
|
+
this.setState({ animation }, () => {
|
|
182
|
+
this._animationFrame = setTimeout(this._animation, 16.667);
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
else {
|
|
187
|
+
this._lastTime = undefined;
|
|
188
|
+
this._animationEnd();
|
|
189
|
+
}
|
|
190
|
+
};
|
|
191
|
+
_animationEnd = () => {
|
|
192
|
+
const hasViewportMoved = !this.state.origin.isAlmostEqual(this.state.startOrigin) ||
|
|
193
|
+
!this.state.rotation.isAlmostEqual(this.state.startRotation);
|
|
194
|
+
const startMapOrigin = Point3d.createFrom(this.state.mapOrigin);
|
|
195
|
+
const startMapExtents = Vector3d.createFrom(this.state.mapExtents);
|
|
196
|
+
const startDrawingZoom = this.state.drawingZoom;
|
|
197
|
+
const startOrigin = this.state.origin;
|
|
198
|
+
const startRotation = this.state.rotation;
|
|
199
|
+
if (this._mounted) {
|
|
200
|
+
this.setState({
|
|
201
|
+
startMapOrigin,
|
|
202
|
+
startDrawingZoom,
|
|
203
|
+
startOrigin,
|
|
204
|
+
startRotation,
|
|
205
|
+
startMapExtents,
|
|
206
|
+
}, () => {
|
|
207
|
+
if (this.props.onAnimationEnd)
|
|
208
|
+
this.props.onAnimationEnd();
|
|
209
|
+
if (hasViewportMoved)
|
|
210
|
+
this._updateFrustum(true);
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
};
|
|
214
|
+
_lastPanTime;
|
|
215
|
+
_panAnimation = () => {
|
|
216
|
+
const t = Date.now();
|
|
217
|
+
if (this._lastPanTime === undefined)
|
|
218
|
+
this._lastPanTime = t - 16.667;
|
|
219
|
+
const delta = t - this._lastPanTime;
|
|
220
|
+
this._lastPanTime = t;
|
|
221
|
+
if (!this.state.panningDirection.isAlmostZero && this.state.isMoving) {
|
|
222
|
+
const { panningDirection } = this.state;
|
|
223
|
+
const offset = panningDirection.scale(delta / 1000 / this.state.drawingZoom);
|
|
224
|
+
const mapOrigin = this.state.mapOrigin.plus(offset);
|
|
225
|
+
const origin = this.state.origin.plus(offset);
|
|
226
|
+
this._updateFrustum();
|
|
227
|
+
if (this._mounted) {
|
|
228
|
+
this.setState({ mapOrigin, origin, panningDirection }, () => {
|
|
229
|
+
this._animationFrame = setTimeout(this._panAnimation, 16.667);
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
else {
|
|
234
|
+
this._lastPanTime = undefined;
|
|
235
|
+
this._updateFrustum(true);
|
|
236
|
+
}
|
|
237
|
+
};
|
|
530
238
|
componentDidMount() {
|
|
531
239
|
this._mounted = true;
|
|
532
240
|
ViewportComponentEvents.onViewRotationChangeEvent.addListener(this._handleViewRotationChangeEvent);
|
|
@@ -550,6 +258,74 @@ export class DrawingNavigationAid extends React.Component {
|
|
|
550
258
|
}
|
|
551
259
|
this._mounted = false;
|
|
552
260
|
}
|
|
261
|
+
// Synchronize with rotation coming from the Viewport
|
|
262
|
+
_handleViewRotationChangeEvent = (args) => {
|
|
263
|
+
if (!this.state.isMoving &&
|
|
264
|
+
!this.state.isPanning &&
|
|
265
|
+
this.props.viewport === args.viewport) {
|
|
266
|
+
const extents = args.viewport.view.getExtents().clone();
|
|
267
|
+
const rotation = args.viewport.view.getRotation().clone();
|
|
268
|
+
const halfExtents = extents.scale(0.5);
|
|
269
|
+
const offset = this.state.rotateMinimapWithView || this._isViewport3D()
|
|
270
|
+
? rotation.multiplyTransposeVector(halfExtents)
|
|
271
|
+
: halfExtents;
|
|
272
|
+
const origin = args.viewport.view.getOrigin().plus(offset);
|
|
273
|
+
const deltaZoom = (this.state.extents.x - extents.x) / this.state.extents.x;
|
|
274
|
+
let drawingZoom = this.state.drawingZoom / (1 - deltaZoom);
|
|
275
|
+
const deltaOrigin = origin.minus(this.state.origin);
|
|
276
|
+
let mapOrigin = this.state.mapOrigin.plus(deltaOrigin);
|
|
277
|
+
mapOrigin = mapOrigin.plus(Vector3d.createFrom(origin.minus(mapOrigin)).scale(deltaZoom));
|
|
278
|
+
if (this.state.viewId !== args.viewport.view.id) {
|
|
279
|
+
const rect = this.state.rotateMinimapWithView || this._isViewport3D()
|
|
280
|
+
? extents
|
|
281
|
+
: DrawingNavigationAid.findRotatedWindowDimensions(extents, rotation);
|
|
282
|
+
const maxRectDim = Math.max(rect.y, rect.x);
|
|
283
|
+
const maxExtentDim = Math.max(this.state.mapExtents.x, this.state.mapExtents.y);
|
|
284
|
+
drawingZoom = maxExtentDim / (3 * maxRectDim);
|
|
285
|
+
mapOrigin = origin.clone();
|
|
286
|
+
this._viewport = args.viewport;
|
|
287
|
+
this.setState({
|
|
288
|
+
viewId: args.viewport.view.id,
|
|
289
|
+
view: args.viewport.view.clone(),
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
if (this._mounted) {
|
|
293
|
+
this.setState({
|
|
294
|
+
startOrigin: origin,
|
|
295
|
+
origin,
|
|
296
|
+
extents,
|
|
297
|
+
startRotation: rotation,
|
|
298
|
+
rotation,
|
|
299
|
+
startMapOrigin: mapOrigin,
|
|
300
|
+
mapOrigin,
|
|
301
|
+
startDrawingZoom: drawingZoom,
|
|
302
|
+
drawingZoom,
|
|
303
|
+
});
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
};
|
|
307
|
+
_updateFrustum = (complete = false) => {
|
|
308
|
+
const halfExtents = this.state.extents.scale(0.5);
|
|
309
|
+
const offset = this.state.rotateMinimapWithView || this._isViewport3D()
|
|
310
|
+
? this.state.rotation.multiplyTransposeVector(halfExtents)
|
|
311
|
+
: halfExtents;
|
|
312
|
+
const origin = this.state.origin.minus(offset);
|
|
313
|
+
ViewportComponentEvents.setDrawingViewportState(origin, this.state.rotation, complete);
|
|
314
|
+
};
|
|
315
|
+
_toggleRotationMode = () => {
|
|
316
|
+
const rotateMinimapWithView = !this.state.rotateMinimapWithView;
|
|
317
|
+
this.setState({ rotateMinimapWithView }, () => {
|
|
318
|
+
if (this._viewport)
|
|
319
|
+
this._handleViewRotationChangeEvent({ viewport: this._viewport });
|
|
320
|
+
});
|
|
321
|
+
};
|
|
322
|
+
_handleKeyUp = (event) => {
|
|
323
|
+
if (event.key === Key.Escape.valueOf() &&
|
|
324
|
+
this.state.mode === MapMode.Opened) {
|
|
325
|
+
this._closeLargeMap();
|
|
326
|
+
}
|
|
327
|
+
};
|
|
328
|
+
_lastClientXY = Point2d.createZero();
|
|
553
329
|
_processWindowDrag(movement) {
|
|
554
330
|
const vect = Vector3d.create(movement.x / this.state.drawingZoom, -movement.y / this.state.drawingZoom, 0);
|
|
555
331
|
const offset = this.state.rotateMinimapWithView || this._isViewport3D()
|
|
@@ -580,58 +356,275 @@ export class DrawingNavigationAid extends React.Component {
|
|
|
580
356
|
}, 0);
|
|
581
357
|
}
|
|
582
358
|
}
|
|
359
|
+
_handleMouseDown = (event) => {
|
|
360
|
+
// Used only to determine if mouse was moved between mousedown and mouseup
|
|
361
|
+
const mouseStart = Point2d.create(event.clientX, event.clientY);
|
|
362
|
+
this.setState({ mouseStart });
|
|
363
|
+
this._lastClientXY = Point2d.create(event.clientX, event.clientY);
|
|
364
|
+
};
|
|
365
|
+
_handleDrawingMouseDown = (event) => {
|
|
366
|
+
if (this.state.mode === MapMode.Opened) {
|
|
367
|
+
event.preventDefault();
|
|
368
|
+
this.setState({ isPanning: true });
|
|
369
|
+
}
|
|
370
|
+
};
|
|
371
|
+
_handleWindowMouseDown = (event) => {
|
|
372
|
+
event.preventDefault();
|
|
373
|
+
this.setState({ isMoving: true });
|
|
374
|
+
};
|
|
375
|
+
_handleMouseDrag = (event) => {
|
|
376
|
+
const mouse = Point2d.create(event.clientX, event.clientY);
|
|
377
|
+
const movement = mouse.minus(this._lastClientXY);
|
|
378
|
+
if (this.state.isMoving) {
|
|
379
|
+
// add scaled mouse movement
|
|
380
|
+
this._processWindowDrag(movement);
|
|
381
|
+
}
|
|
382
|
+
else {
|
|
383
|
+
if (this.state.isPanning && this.state.mode === MapMode.Opened) {
|
|
384
|
+
const vect = Vector3d.create(movement.x / this.state.drawingZoom, -movement.y / this.state.drawingZoom, 0);
|
|
385
|
+
const offset = this.state.rotateMinimapWithView || this._isViewport3D()
|
|
386
|
+
? this.state.rotation.multiplyTransposeVector(vect)
|
|
387
|
+
: vect;
|
|
388
|
+
const mapOrigin = this.state.mapOrigin.minus(offset);
|
|
389
|
+
this.setState({ startMapOrigin: mapOrigin, mapOrigin });
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
this._lastClientXY = mouse;
|
|
393
|
+
};
|
|
394
|
+
_handleMouseDragEnd = (event) => {
|
|
395
|
+
const mouse = Point2d.create(event.clientX, event.clientY);
|
|
396
|
+
if (mouse.isAlmostEqual(this.state.mouseStart) &&
|
|
397
|
+
this.state.mode === MapMode.Closed &&
|
|
398
|
+
(event.target === this._viewContainerElement.current ||
|
|
399
|
+
event.target === this._viewElement.current)) {
|
|
400
|
+
this._openLargeMap();
|
|
401
|
+
}
|
|
402
|
+
else if (this.state.isMoving) {
|
|
403
|
+
this._processWindowEndDrag();
|
|
404
|
+
}
|
|
405
|
+
else if (this.state.isPanning) {
|
|
406
|
+
if (this.state.mode === MapMode.Opened) {
|
|
407
|
+
event.stopPropagation();
|
|
408
|
+
this.setState({ isPanning: false });
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
else if ((!(event.target instanceof Node) ||
|
|
412
|
+
(this._rootElement.current &&
|
|
413
|
+
!this._rootElement.current.contains(event.target))) &&
|
|
414
|
+
mouse.isAlmostEqual(this.state.mouseStart)) {
|
|
415
|
+
this._closeLargeMap();
|
|
416
|
+
}
|
|
417
|
+
this._lastClientXY = Point2d.create(event.clientX, event.clientY);
|
|
418
|
+
};
|
|
419
|
+
_handleWindowTouchStart = (event) => {
|
|
420
|
+
if (1 !== event.targetTouches.length)
|
|
421
|
+
return;
|
|
422
|
+
window.addEventListener("touchmove", this._onTouchMove, false);
|
|
423
|
+
window.addEventListener("touchend", this._onTouchEnd, false);
|
|
424
|
+
const mouseStart = Point2d.create(event.targetTouches[0].clientX, event.targetTouches[0].clientY);
|
|
425
|
+
this.setState({ mouseStart });
|
|
426
|
+
this._lastClientXY = mouseStart.clone();
|
|
427
|
+
this.setState({ isMoving: true });
|
|
428
|
+
};
|
|
429
|
+
_onTouchMove = (event) => {
|
|
430
|
+
if (1 !== event.targetTouches.length)
|
|
431
|
+
return;
|
|
432
|
+
const mouse = Point2d.create(event.targetTouches[0].clientX, event.targetTouches[0].clientY);
|
|
433
|
+
const movement = mouse.minus(this._lastClientXY);
|
|
434
|
+
// add scaled mouse movement
|
|
435
|
+
this._processWindowDrag(movement);
|
|
436
|
+
this._lastClientXY = mouse;
|
|
437
|
+
};
|
|
438
|
+
_onTouchEnd = (event) => {
|
|
439
|
+
if (0 !== event.targetTouches.length)
|
|
440
|
+
return;
|
|
441
|
+
this._processWindowEndDrag();
|
|
442
|
+
if (0 !== event.changedTouches.length)
|
|
443
|
+
this._lastClientXY = Point2d.create(event.changedTouches[0].clientX, event.changedTouches[0].clientY); // Doesn't seem necessary...but _handleMouseDragEnd sets it...
|
|
444
|
+
window.removeEventListener("touchmove", this._onTouchMove);
|
|
445
|
+
window.removeEventListener("touchend", this._onTouchEnd);
|
|
446
|
+
};
|
|
447
|
+
/** @internal */
|
|
448
|
+
static getDefaultClosedMapSize = () => {
|
|
449
|
+
return Vector3d.create(96, 96);
|
|
450
|
+
};
|
|
451
|
+
/** @internal */
|
|
452
|
+
static getDefaultOpenedMapSize = (paddingX = 0, paddingY = 0) => {
|
|
453
|
+
return Vector3d.create(window.innerWidth / 3 - 2 * (window.innerWidth - paddingX), window.innerHeight / 3 - 2 * paddingY);
|
|
454
|
+
};
|
|
455
|
+
_getClosedMapSize = () => {
|
|
456
|
+
if (this.props.closeSize === undefined)
|
|
457
|
+
return DrawingNavigationAid.getDefaultClosedMapSize();
|
|
458
|
+
return this.props.closeSize;
|
|
459
|
+
};
|
|
460
|
+
_getOpenedMapSize = () => {
|
|
461
|
+
if (this.props.openSize === undefined)
|
|
462
|
+
return DrawingNavigationAid.getDefaultOpenedMapSize(this._rootOffset.right, this._rootOffset.top);
|
|
463
|
+
return this.props.openSize;
|
|
464
|
+
};
|
|
465
|
+
_openLargeMap = () => {
|
|
466
|
+
if (this.state.mode === MapMode.Closed && this.state.animation === 1.0) {
|
|
467
|
+
if (this._rootElement.current) {
|
|
468
|
+
const rect = this._rootElement.current.getBoundingClientRect();
|
|
469
|
+
this._rootOffset = rect;
|
|
470
|
+
}
|
|
471
|
+
const startMapExtents = Vector3d.createFrom(this.state.mapExtents);
|
|
472
|
+
const mapExtents = this._getOpenedMapSize();
|
|
473
|
+
this.setState({
|
|
474
|
+
mode: MapMode.Opened,
|
|
475
|
+
isMoving: false,
|
|
476
|
+
isPanning: false,
|
|
477
|
+
mapExtents,
|
|
478
|
+
startMapExtents,
|
|
479
|
+
animation: 0,
|
|
480
|
+
}, () => {
|
|
481
|
+
this._animationFrame = setTimeout(this._animation);
|
|
482
|
+
});
|
|
483
|
+
}
|
|
484
|
+
};
|
|
485
|
+
_closeLargeMap = () => {
|
|
486
|
+
if (this.state.mode === MapMode.Opened && this.state.animation === 1.0) {
|
|
487
|
+
const startMapOrigin = this.state.mapOrigin;
|
|
488
|
+
const mapOrigin = this.state.origin.clone();
|
|
489
|
+
const startMapExtents = Vector3d.createFrom(this.state.mapExtents);
|
|
490
|
+
const mapExtents = this._getClosedMapSize();
|
|
491
|
+
const rect = this.state.rotateMinimapWithView || this._isViewport3D()
|
|
492
|
+
? this.state.extents
|
|
493
|
+
: DrawingNavigationAid.findRotatedWindowDimensions(this.state.extents, this.state.rotation);
|
|
494
|
+
const maxRectDim = Math.max(rect.y, rect.x);
|
|
495
|
+
const maxExtentDim = Math.max(mapExtents.x, mapExtents.y);
|
|
496
|
+
const drawingZoom = maxExtentDim / (3 * maxRectDim);
|
|
497
|
+
const startDrawingZoom = this.state.drawingZoom;
|
|
498
|
+
this.setState({
|
|
499
|
+
mode: MapMode.Closed,
|
|
500
|
+
startMapOrigin,
|
|
501
|
+
mapOrigin,
|
|
502
|
+
startDrawingZoom,
|
|
503
|
+
drawingZoom,
|
|
504
|
+
isMoving: false,
|
|
505
|
+
isPanning: false,
|
|
506
|
+
startMapExtents,
|
|
507
|
+
mapExtents,
|
|
508
|
+
panningDirection: Vector3d.createZero(),
|
|
509
|
+
animation: 0,
|
|
510
|
+
}, () => {
|
|
511
|
+
this._animationFrame = setTimeout(this._animation, 16.667);
|
|
512
|
+
});
|
|
513
|
+
}
|
|
514
|
+
};
|
|
515
|
+
_getPanVector = () => {
|
|
516
|
+
const is3D = this._isViewport3D();
|
|
517
|
+
const rect = this.state.rotateMinimapWithView || is3D
|
|
518
|
+
? this.state.extents
|
|
519
|
+
: DrawingNavigationAid.findRotatedWindowDimensions(this.state.extents, this.state.rotation);
|
|
520
|
+
const mapExtents = this.state.mapExtents.scale(1 / this.state.drawingZoom);
|
|
521
|
+
const maxMagnitude = 80; // maximum acceleration
|
|
522
|
+
const magnitudeTravel = 30; // How far, in pixels, that magnitude increases from 0 to max acceleration
|
|
523
|
+
const diff = Vector3d.createFrom(this.state.origin.minus(this.state.mapOrigin));
|
|
524
|
+
const diffVector = this.state.rotateMinimapWithView || is3D
|
|
525
|
+
? this.state.rotation.multiplyVector(diff)
|
|
526
|
+
: diff;
|
|
527
|
+
// capture any values
|
|
528
|
+
const magnitudeVector = Vector3d.create(Math.max(0, Math.abs(diffVector.x) - (mapExtents.x - rect.x) / 2), Math.max(0, Math.abs(diffVector.y) - (mapExtents.y - rect.y) / 2));
|
|
529
|
+
if (magnitudeVector.isAlmostZero)
|
|
530
|
+
return Vector3d.createZero();
|
|
531
|
+
const magnitude = (Math.min(magnitudeVector.magnitude() * this.state.drawingZoom, magnitudeTravel) /
|
|
532
|
+
magnitudeTravel) *
|
|
533
|
+
maxMagnitude;
|
|
534
|
+
const vect = Vector3d.createFrom(this.state.origin.minus(this.state.mapOrigin)); // vect will never be zero or magnitude would also be zero
|
|
535
|
+
const norm = vect.normalize();
|
|
536
|
+
return norm.scale(magnitude); // norm is only undefined when vect is zero, in which it would have returned at magnitudeVector.isAlmostZero
|
|
537
|
+
};
|
|
538
|
+
_handleWheel = (event) => {
|
|
539
|
+
if (this.state.mode === MapMode.Opened && this.state.animation === 1) {
|
|
540
|
+
const { mapOrigin, drawingZoom } = this.state;
|
|
541
|
+
const mapSize = this._getOpenedMapSize();
|
|
542
|
+
const mouseX = event.clientX - this._rootOffset.right + mapSize.x / 2;
|
|
543
|
+
const mouseY = event.clientY - this._rootOffset.top - mapSize.y / 2;
|
|
544
|
+
const is3D = this._isViewport3D();
|
|
545
|
+
if (event.deltaY < 0) {
|
|
546
|
+
const zoom = drawingZoom * 1.1;
|
|
547
|
+
const vect = Vector3d.create((mouseX * 0.1) / zoom, (-mouseY * 0.1) / zoom, 0);
|
|
548
|
+
const offset = this.state.rotateMinimapWithView || is3D
|
|
549
|
+
? this.state.rotation.multiplyTransposeVector(vect)
|
|
550
|
+
: vect;
|
|
551
|
+
const m = mapOrigin.plus(offset);
|
|
552
|
+
this.setState({ mapOrigin: m, drawingZoom: zoom });
|
|
553
|
+
}
|
|
554
|
+
if (event.deltaY > 0) {
|
|
555
|
+
const zoom = drawingZoom / 1.1;
|
|
556
|
+
const vect = Vector3d.create((mouseX * 0.1) / drawingZoom, (-mouseY * 0.1) / drawingZoom, 0);
|
|
557
|
+
const offset = this.state.rotateMinimapWithView || is3D
|
|
558
|
+
? this.state.rotation.multiplyTransposeVector(vect)
|
|
559
|
+
: vect;
|
|
560
|
+
const m = mapOrigin.minus(offset);
|
|
561
|
+
this.setState({ mapOrigin: m, drawingZoom: zoom });
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
};
|
|
565
|
+
_handleZoomIn = () => {
|
|
566
|
+
const zoom = this.state.drawingZoom * 1.4;
|
|
567
|
+
this.setState({ drawingZoom: zoom });
|
|
568
|
+
};
|
|
569
|
+
_handleZoomOut = () => {
|
|
570
|
+
const zoom = this.state.drawingZoom / 1.4;
|
|
571
|
+
this.setState({ drawingZoom: zoom });
|
|
572
|
+
};
|
|
573
|
+
_handleUnrotate = () => {
|
|
574
|
+
const startRotation = this.state.rotation;
|
|
575
|
+
const halfExtents = this.state.extents.scale(0.5);
|
|
576
|
+
const offset = this.state.rotateMinimapWithView || this._isViewport3D()
|
|
577
|
+
? Vector3d.createZero()
|
|
578
|
+
: this.state.rotation
|
|
579
|
+
.multiplyTransposeVector(halfExtents)
|
|
580
|
+
.minus(halfExtents);
|
|
581
|
+
const startOrigin = this.state.origin;
|
|
582
|
+
const origin = this.state.origin.plus(offset);
|
|
583
|
+
const startMapOrigin = this.state.mapOrigin;
|
|
584
|
+
const mapOrigin = this.state.mapOrigin.plus(offset);
|
|
585
|
+
this.setState({
|
|
586
|
+
animation: 0,
|
|
587
|
+
startOrigin,
|
|
588
|
+
origin,
|
|
589
|
+
startMapOrigin,
|
|
590
|
+
mapOrigin,
|
|
591
|
+
startRotation,
|
|
592
|
+
rotation: Matrix3d.createIdentity(),
|
|
593
|
+
}, () => {
|
|
594
|
+
this._animationFrame = setTimeout(this._animation, 16.667);
|
|
595
|
+
});
|
|
596
|
+
};
|
|
597
|
+
/** @internal */
|
|
598
|
+
static findRotatedWindowDimensions = (extents, rotation) => {
|
|
599
|
+
const cos = rotation.at(0, 0);
|
|
600
|
+
const sin = rotation.at(1, 0);
|
|
601
|
+
// extents.x/y should be divided in half, but we don't have to do that immediately.
|
|
602
|
+
const cosWidth = cos * extents.x;
|
|
603
|
+
const sinHeight = sin * extents.y;
|
|
604
|
+
const sinWidth = cos * extents.x;
|
|
605
|
+
const cosHeight = sin * extents.y;
|
|
606
|
+
const a = Math.atan2(sin, cos);
|
|
607
|
+
if (a % Math.PI >= 0 && a % Math.PI < Math.PI / 2) {
|
|
608
|
+
const y1 = -cosHeight - sinWidth;
|
|
609
|
+
const x2 = cosWidth + sinHeight;
|
|
610
|
+
const y3 = cosHeight + sinWidth;
|
|
611
|
+
const x4 = -cosWidth - sinHeight;
|
|
612
|
+
// Instead, divide total difference
|
|
613
|
+
return Vector3d.create(Math.abs(x2 - x4) / 2, Math.abs(y1 - y3) / 2);
|
|
614
|
+
}
|
|
615
|
+
else {
|
|
616
|
+
const x1 = -cosWidth + sinHeight;
|
|
617
|
+
const y2 = -cosHeight + sinWidth;
|
|
618
|
+
const x3 = cosWidth - sinHeight;
|
|
619
|
+
const y4 = cosHeight - sinWidth;
|
|
620
|
+
return Vector3d.create(Math.abs(x1 - x3) / 2, Math.abs(y2 - y4) / 2);
|
|
621
|
+
}
|
|
622
|
+
};
|
|
583
623
|
}
|
|
584
|
-
DrawingNavigationAid._animationFn = (t) => t < 0.5 ? 2 * t ** 2 : -1 + (4 - 2 * t) * t;
|
|
585
|
-
/** @internal */
|
|
586
|
-
DrawingNavigationAid.getDefaultClosedMapSize = () => {
|
|
587
|
-
return Vector3d.create(96, 96);
|
|
588
|
-
};
|
|
589
|
-
/** @internal */
|
|
590
|
-
DrawingNavigationAid.getDefaultOpenedMapSize = (paddingX = 0, paddingY = 0) => {
|
|
591
|
-
return Vector3d.create(window.innerWidth / 3 - 2 * (window.innerWidth - paddingX), window.innerHeight / 3 - 2 * paddingY);
|
|
592
|
-
};
|
|
593
|
-
/** @internal */
|
|
594
|
-
DrawingNavigationAid.findRotatedWindowDimensions = (extents, rotation) => {
|
|
595
|
-
const cos = rotation.at(0, 0);
|
|
596
|
-
const sin = rotation.at(1, 0);
|
|
597
|
-
// extents.x/y should be divided in half, but we don't have to do that immediately.
|
|
598
|
-
const cosWidth = cos * extents.x;
|
|
599
|
-
const sinHeight = sin * extents.y;
|
|
600
|
-
const sinWidth = cos * extents.x;
|
|
601
|
-
const cosHeight = sin * extents.y;
|
|
602
|
-
const a = Math.atan2(sin, cos);
|
|
603
|
-
if (a % Math.PI >= 0 && a % Math.PI < Math.PI / 2) {
|
|
604
|
-
const y1 = -cosHeight - sinWidth;
|
|
605
|
-
const x2 = cosWidth + sinHeight;
|
|
606
|
-
const y3 = cosHeight + sinWidth;
|
|
607
|
-
const x4 = -cosWidth - sinHeight;
|
|
608
|
-
// Instead, divide total difference
|
|
609
|
-
return Vector3d.create(Math.abs(x2 - x4) / 2, Math.abs(y1 - y3) / 2);
|
|
610
|
-
}
|
|
611
|
-
else {
|
|
612
|
-
const x1 = -cosWidth + sinHeight;
|
|
613
|
-
const y2 = -cosHeight + sinWidth;
|
|
614
|
-
const x3 = cosWidth - sinHeight;
|
|
615
|
-
const y4 = cosHeight - sinWidth;
|
|
616
|
-
return Vector3d.create(Math.abs(x1 - x3) / 2, Math.abs(y2 - y4) / 2);
|
|
617
|
-
}
|
|
618
|
-
};
|
|
619
624
|
/** @internal */
|
|
620
625
|
export class DrawingNavigationCanvas extends React.Component {
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
this._canvasElement = React.createRef();
|
|
624
|
-
this._update = () => {
|
|
625
|
-
if (this._vp) {
|
|
626
|
-
const max = Math.max(this.props.extents.x, this.props.extents.y);
|
|
627
|
-
this._vp.view.extentLimits = { max, min: Constant.oneMillimeter };
|
|
628
|
-
this._vp.view.setOrigin(this.props.origin);
|
|
629
|
-
this._vp.view.setRotation(this.props.rotation);
|
|
630
|
-
this._vp.view.setExtents(this.props.extents);
|
|
631
|
-
this._vp.applyViewState(this._vp.view);
|
|
632
|
-
}
|
|
633
|
-
};
|
|
634
|
-
}
|
|
626
|
+
_canvasElement = React.createRef();
|
|
627
|
+
_vp;
|
|
635
628
|
render() {
|
|
636
629
|
return (React.createElement("div", { className: "drawing-canvas", "data-testid": "drawing-canvas", ref: this._canvasElement }));
|
|
637
630
|
}
|
|
@@ -657,6 +650,16 @@ export class DrawingNavigationCanvas extends React.Component {
|
|
|
657
650
|
if (vp.viewFlags.acsTriad)
|
|
658
651
|
vp.viewFlags = vp.viewFlags.with("acsTriad", false);
|
|
659
652
|
}
|
|
653
|
+
_update = () => {
|
|
654
|
+
if (this._vp) {
|
|
655
|
+
const max = Math.max(this.props.extents.x, this.props.extents.y);
|
|
656
|
+
this._vp.view.extentLimits = { max, min: Constant.oneMillimeter };
|
|
657
|
+
this._vp.view.setOrigin(this.props.origin);
|
|
658
|
+
this._vp.view.setRotation(this.props.rotation);
|
|
659
|
+
this._vp.view.setExtents(this.props.extents);
|
|
660
|
+
this._vp.applyViewState(this._vp.view);
|
|
661
|
+
}
|
|
662
|
+
};
|
|
660
663
|
componentDidUpdate(oldProps) {
|
|
661
664
|
const viewManager = this.props.viewManagerOverride
|
|
662
665
|
? this.props.viewManagerOverride
|