@xeokit/xeokit-sdk 2.6.0-beta-11 → 2.6.0-beta-13
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/dist/xeokit-sdk.cjs.js +1881 -1
- package/dist/xeokit-sdk.es.js +1879 -2
- package/dist/xeokit-sdk.es5.js +909 -639
- package/dist/xeokit-sdk.min.cjs.js +5 -5
- package/dist/xeokit-sdk.min.es.js +5 -5
- package/dist/xeokit-sdk.min.es5.js +4 -4
- package/package.json +1 -1
- package/src/extras/PointerCircle/PointerCircle.js +135 -0
- package/src/extras/PointerCircle/index.js +1 -0
- package/src/extras/index.js +2 -1
- package/src/plugins/AngleMeasurementsPlugin/AngleMeasurementsPlugin.js +40 -0
- package/src/plugins/AngleMeasurementsPlugin/AngleMeasurementsTouchControl.js +916 -0
- package/src/plugins/AngleMeasurementsPlugin/index.js +2 -1
- package/src/plugins/DistanceMeasurementsPlugin/DistanceMeasurementsControlLegacy.js +472 -0
- package/src/plugins/DistanceMeasurementsPlugin/DistanceMeasurementsPlugin.js +41 -1
- package/src/plugins/DistanceMeasurementsPlugin/DistanceMeasurementsTouchControl.js +753 -0
- package/src/plugins/DistanceMeasurementsPlugin/index.js +1 -0
- package/src/viewer/Viewer.js +2 -2
- package/src/viewer/scene/webgl/PickResult.js +8 -0
|
@@ -0,0 +1,472 @@
|
|
|
1
|
+
import {Dot} from "../lib/html/Dot.js";
|
|
2
|
+
import {Component} from "../../viewer/scene/Component.js";
|
|
3
|
+
import {math} from "../../viewer/scene/math/math.js";
|
|
4
|
+
import {Marker} from "../../viewer/index.js";
|
|
5
|
+
import {DistanceMeasurementsControl} from "./DistanceMeasurementsControl";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Creates {@link DistanceMeasurement}s from mouse and touch input.
|
|
9
|
+
*
|
|
10
|
+
* Belongs to a {@link DistanceMeasurementsPlugin}. Located at {@link DistanceMeasurementsPlugin#control}.
|
|
11
|
+
*
|
|
12
|
+
* Once the DistanceMeasurementControl is activated, the first click on any {@link Entity} begins constructing a {@link DistanceMeasurement}, fixing its origin to that Entity. The next click on any Entity will complete the DistanceMeasurement, fixing its target to that second Entity. The DistanceMeasurementControl will then wait for the next click on any Entity, to begin constructing another DistanceMeasurement, and so on, until deactivated.
|
|
13
|
+
*
|
|
14
|
+
* See {@link DistanceMeasurementsPlugin} for more info.
|
|
15
|
+
*/
|
|
16
|
+
export class DistanceMeasurementsControlLegacy extends DistanceMeasurementsControl {
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* @private
|
|
20
|
+
*/
|
|
21
|
+
constructor(plugin, cfg={}) {
|
|
22
|
+
|
|
23
|
+
super(plugin.viewer.scene);
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* The {@link DistanceMeasurementsPlugin} that owns this DistanceMeasurementsControlLegacy.
|
|
27
|
+
* @type {DistanceMeasurementsPlugin}
|
|
28
|
+
*/
|
|
29
|
+
this.plugin = plugin;
|
|
30
|
+
|
|
31
|
+
this._active = false;
|
|
32
|
+
this._snapMode = "off";
|
|
33
|
+
this._snapToVertex = false;
|
|
34
|
+
|
|
35
|
+
// Add a marker to the canvas
|
|
36
|
+
const markerDiv = document.createElement('div');
|
|
37
|
+
const canvas = this.scene.canvas.canvas;
|
|
38
|
+
canvas.parentNode.insertBefore(markerDiv, canvas);
|
|
39
|
+
|
|
40
|
+
markerDiv.style.background = "black";
|
|
41
|
+
markerDiv.style.border = "2px solid blue";
|
|
42
|
+
markerDiv.style.borderRadius = "10px";
|
|
43
|
+
markerDiv.style.width = "5px";
|
|
44
|
+
markerDiv.style.height = "5px";
|
|
45
|
+
markerDiv.style.margin = "-200px -200px";
|
|
46
|
+
markerDiv.style.zIndex = "100";
|
|
47
|
+
markerDiv.style.position = "absolute";
|
|
48
|
+
markerDiv.style.pointerEvents = "none";
|
|
49
|
+
|
|
50
|
+
this.markerDiv = markerDiv;
|
|
51
|
+
|
|
52
|
+
// Mouse input uses a combo of events that requires us to track
|
|
53
|
+
// the current DistanceMeasurement under construction. This is not used for touch input, which
|
|
54
|
+
// just uses touch-move-release to make a measurement.
|
|
55
|
+
this._currentDistanceMeasurementByMouse = null;
|
|
56
|
+
|
|
57
|
+
this._currentDistanceMeasurementByMouseInittouchState = {
|
|
58
|
+
wireVisible: null,
|
|
59
|
+
axisVisible: null,
|
|
60
|
+
xAxisVisible: null,
|
|
61
|
+
yaxisVisible: null,
|
|
62
|
+
zAxisVisible: null,
|
|
63
|
+
targetVisible: null,
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Shows 2D canvas pos of touch start
|
|
67
|
+
this._touchStartDot = new Dot(plugin._container, {
|
|
68
|
+
fillColor: plugin.defaultColor,
|
|
69
|
+
zIndex: plugin.zIndex + 1,
|
|
70
|
+
visible: false
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
// Tracks 3D world pos of touch start, dynamically calculates 2D canvas pos
|
|
74
|
+
this._touchStartMarker = new Marker(this, {
|
|
75
|
+
id: "distanceMeasurementMarker"
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
// Routes 2D canvas pos from Marker to Dot
|
|
79
|
+
this._touchStartMarker.on("canvasPos", (canvasPos) => {
|
|
80
|
+
this._touchStartDot.setPos(canvasPos[0], canvasPos[1]);
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
// Event handles from CameraControl
|
|
84
|
+
this._onMouseHoverSurface = null;
|
|
85
|
+
this._onMouseHoverOff = null;
|
|
86
|
+
this._onPickedNothing = null;
|
|
87
|
+
|
|
88
|
+
// Event handles from Scene.input
|
|
89
|
+
this._onInputMouseDown = null;
|
|
90
|
+
this._onInputMouseUp = null;
|
|
91
|
+
|
|
92
|
+
// Event handles from Canvas element
|
|
93
|
+
this._onCanvasTouchStart = null;
|
|
94
|
+
this._onCanvasTouchEnd = null;
|
|
95
|
+
|
|
96
|
+
this.snapMode = cfg.snapMode;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Sets the pointer snapping behaviour.
|
|
101
|
+
*
|
|
102
|
+
* Accepted values are "off" and "vertex".
|
|
103
|
+
*
|
|
104
|
+
* If set to "vertex", the DistanceMeasurementsPlugin will continuously snap the pointer to the nearest vertex as the user hovers over the model.
|
|
105
|
+
*
|
|
106
|
+
* @param snapMode {String}
|
|
107
|
+
*/
|
|
108
|
+
set snapMode(snapMode) {
|
|
109
|
+
if (snapMode === undefined || snapMode === null) {
|
|
110
|
+
snapMode = "vertex";
|
|
111
|
+
} else if (snapMode !== "vertex") {
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
this._snapMode = snapMode;
|
|
115
|
+
this._snapToVertex = (snapMode === "vertex");
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Gets the pointer snapping behaviour.
|
|
120
|
+
*
|
|
121
|
+
* Accepted values are "off" and "vertex".
|
|
122
|
+
*
|
|
123
|
+
* If set to "vertex", the DistanceMeasurementsPlugin will continuously snap the pointer to the nearest vertex as the user hovers over the model.
|
|
124
|
+
*
|
|
125
|
+
* @returns {String}
|
|
126
|
+
*/
|
|
127
|
+
get snapMode() {
|
|
128
|
+
return this._snapMode;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/** Gets if this DistanceMeasurementsControlLegacy is currently active, where it is responding to input.
|
|
132
|
+
*
|
|
133
|
+
* @returns {Boolean}
|
|
134
|
+
*/
|
|
135
|
+
get active() {
|
|
136
|
+
return this._active;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Activates this DistanceMeasurementsControlLegacy, ready to respond to input.
|
|
141
|
+
*
|
|
142
|
+
*/
|
|
143
|
+
activate() {
|
|
144
|
+
|
|
145
|
+
if (this._active) {
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
const plugin = this.plugin;
|
|
150
|
+
const scene = this.scene;
|
|
151
|
+
const cameraControl = plugin.viewer.cameraControl;
|
|
152
|
+
const canvas = scene.canvas.canvas;
|
|
153
|
+
const input = scene.input;
|
|
154
|
+
const startDot = this._touchStartDot;
|
|
155
|
+
|
|
156
|
+
const pickSurfacePrecisionEnabled = scene.pickSurfacePrecisionEnabled;
|
|
157
|
+
|
|
158
|
+
let mouseHoverEntity = null;
|
|
159
|
+
const mouseWorldPos = math.vec3();
|
|
160
|
+
const mouseCanvasPos = math.vec2();
|
|
161
|
+
|
|
162
|
+
let lastMouseCanvasX;
|
|
163
|
+
let lastMouseCanvasY;
|
|
164
|
+
const mouseCanvasClickTolerance = 5;
|
|
165
|
+
|
|
166
|
+
const FIRST_TOUCH_EXPECTED = 0;
|
|
167
|
+
const SECOND_TOUCH_EXPECTED = 1;
|
|
168
|
+
let touchState = FIRST_TOUCH_EXPECTED;
|
|
169
|
+
const touchCanvasClickTolerance = 5;
|
|
170
|
+
|
|
171
|
+
const touchStartCanvasPos = math.vec2();
|
|
172
|
+
const touchEndCanvasPos = math.vec2();
|
|
173
|
+
const touchStartWorldPos = math.vec3();
|
|
174
|
+
|
|
175
|
+
this._onMouseHoverSurface = cameraControl.on("hoverSurface", event => {
|
|
176
|
+
|
|
177
|
+
// This gets fired for both mouse and touch input, but we don't care when handling touch
|
|
178
|
+
mouseHoverEntity = event.entity;
|
|
179
|
+
|
|
180
|
+
let useSnapToVertex = false;
|
|
181
|
+
|
|
182
|
+
if (this._snapToVertex) {
|
|
183
|
+
useSnapToVertex = !!event.snappedWorldPos && !!event.snappedCanvasPos;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
if (useSnapToVertex) {
|
|
187
|
+
mouseWorldPos.set(event.snappedWorldPos);
|
|
188
|
+
mouseCanvasPos.set(event.snappedCanvasPos);
|
|
189
|
+
|
|
190
|
+
if (touchState === FIRST_TOUCH_EXPECTED) {
|
|
191
|
+
this.markerDiv.style.marginLeft = `${event.snappedCanvasPos[0]-5}px`;
|
|
192
|
+
this.markerDiv.style.marginTop = `${event.snappedCanvasPos[1]-5}px`;
|
|
193
|
+
|
|
194
|
+
this.markerDiv.style.background = "greenyellow";
|
|
195
|
+
this.markerDiv.style.border = "2px solid green";
|
|
196
|
+
}
|
|
197
|
+
} else {
|
|
198
|
+
if (event.worldPos !== null && event.canvasPos !== null) {
|
|
199
|
+
mouseWorldPos.set(event.worldPos);
|
|
200
|
+
mouseCanvasPos.set(event.canvasPos);
|
|
201
|
+
|
|
202
|
+
if (touchState === FIRST_TOUCH_EXPECTED) {
|
|
203
|
+
this.markerDiv.style.marginLeft = `${event.canvasPos[0]-5}px`;
|
|
204
|
+
this.markerDiv.style.marginTop = `${event.canvasPos[1]-5}px`;
|
|
205
|
+
|
|
206
|
+
this.markerDiv.style.background = "pink";
|
|
207
|
+
this.markerDiv.style.border = "2px solid red";
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
if (touchState !== FIRST_TOUCH_EXPECTED || !this.active) {
|
|
213
|
+
this.markerDiv.style.marginLeft = `-10000px`;
|
|
214
|
+
this.markerDiv.style.marginTop = `-10000px`;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
canvas.style.cursor = "pointer";
|
|
218
|
+
|
|
219
|
+
if (this._currentDistanceMeasurementByMouse) {
|
|
220
|
+
this._currentDistanceMeasurementByMouse.wireVisible = this._currentDistanceMeasurementByMouseInittouchState.wireVisible;
|
|
221
|
+
this._currentDistanceMeasurementByMouse.axisVisible = this._currentDistanceMeasurementByMouseInittouchState.axisVisible && this.plugin.defaultAxisVisible;
|
|
222
|
+
this._currentDistanceMeasurementByMouse.xAxisVisible = this._currentDistanceMeasurementByMouseInittouchState.xAxisVisible && this.plugin.defaultXAxisVisible;
|
|
223
|
+
this._currentDistanceMeasurementByMouse.yAxisVisible = this._currentDistanceMeasurementByMouseInittouchState.yAxisVisible && this.plugin.defaultYAxisVisible;
|
|
224
|
+
this._currentDistanceMeasurementByMouse.zAxisVisible = this._currentDistanceMeasurementByMouseInittouchState.zAxisVisible && this.plugin.defaultZAxisVisible;
|
|
225
|
+
this._currentDistanceMeasurementByMouse.targetVisible = this._currentDistanceMeasurementByMouseInittouchState.targetVisible;
|
|
226
|
+
this._currentDistanceMeasurementByMouse.target.entity = mouseHoverEntity;
|
|
227
|
+
this._currentDistanceMeasurementByMouse.target.worldPos = mouseWorldPos;
|
|
228
|
+
}
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
this._onInputMouseDown = input.on("mousedown", (coords) => {
|
|
232
|
+
lastMouseCanvasX = coords[0];
|
|
233
|
+
lastMouseCanvasY = coords[1];
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
this._onInputMouseUp = input.on("mouseup", (coords) => {
|
|
237
|
+
if (coords[0] > lastMouseCanvasX + mouseCanvasClickTolerance ||
|
|
238
|
+
coords[0] < lastMouseCanvasX - mouseCanvasClickTolerance ||
|
|
239
|
+
coords[1] > lastMouseCanvasY + mouseCanvasClickTolerance ||
|
|
240
|
+
coords[1] < lastMouseCanvasY - mouseCanvasClickTolerance) {
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
if (this._currentDistanceMeasurementByMouse) {
|
|
244
|
+
if (mouseHoverEntity) {
|
|
245
|
+
if (pickSurfacePrecisionEnabled) {
|
|
246
|
+
const pickResult = scene.pick({
|
|
247
|
+
canvasPos: mouseCanvasPos,
|
|
248
|
+
pickSurface: true,
|
|
249
|
+
pickSurfacePrecision: true
|
|
250
|
+
});
|
|
251
|
+
if (pickResult && pickResult.worldPos) {
|
|
252
|
+
this._currentDistanceMeasurementByMouse.target.worldPos = pickResult.worldPos;
|
|
253
|
+
}
|
|
254
|
+
this._currentDistanceMeasurementByMouse.approximate = false;
|
|
255
|
+
}
|
|
256
|
+
this._currentDistanceMeasurementByMouse.clickable = true;
|
|
257
|
+
this.fire("measurementEnd", this._currentDistanceMeasurementByMouse);
|
|
258
|
+
this._currentDistanceMeasurementByMouse = null;
|
|
259
|
+
} else {
|
|
260
|
+
this._currentDistanceMeasurementByMouse.destroy();
|
|
261
|
+
this.fire("measurementCancel", this._currentDistanceMeasurementByMouse);
|
|
262
|
+
this._currentDistanceMeasurementByMouse = null;
|
|
263
|
+
}
|
|
264
|
+
} else {
|
|
265
|
+
if (mouseHoverEntity) {
|
|
266
|
+
if (pickSurfacePrecisionEnabled) {
|
|
267
|
+
const pickResult = scene.pick({
|
|
268
|
+
canvasPos: mouseCanvasPos,
|
|
269
|
+
pickSurface: true,
|
|
270
|
+
pickSurfacePrecision: true
|
|
271
|
+
});
|
|
272
|
+
if (pickResult && pickResult.worldPos) {
|
|
273
|
+
mouseWorldPos.set(pickResult.worldPos);
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
this._currentDistanceMeasurementByMouse = plugin.createMeasurement({
|
|
277
|
+
id: math.createUUID(),
|
|
278
|
+
origin: {
|
|
279
|
+
entity: mouseHoverEntity,
|
|
280
|
+
worldPos: mouseWorldPos
|
|
281
|
+
},
|
|
282
|
+
target: {
|
|
283
|
+
entity: mouseHoverEntity,
|
|
284
|
+
worldPos: mouseWorldPos
|
|
285
|
+
},
|
|
286
|
+
approximate: true
|
|
287
|
+
});
|
|
288
|
+
this._currentDistanceMeasurementByMouseInittouchState.axisVisible = this._currentDistanceMeasurementByMouse.axisVisible && this.plugin.defaultAxisVisible;
|
|
289
|
+
|
|
290
|
+
this._currentDistanceMeasurementByMouseInittouchState.xAxisVisible = this._currentDistanceMeasurementByMouse.xAxisVisible && this.plugin.defaultXAxisVisible;
|
|
291
|
+
this._currentDistanceMeasurementByMouseInittouchState.yAxisVisible = this._currentDistanceMeasurementByMouse.yAxisVisible && this.plugin.defaultYAxisVisible;
|
|
292
|
+
this._currentDistanceMeasurementByMouseInittouchState.zAxisVisible = this._currentDistanceMeasurementByMouse.zAxisVisible && this.plugin.defaultZAxisVisible;
|
|
293
|
+
|
|
294
|
+
this._currentDistanceMeasurementByMouseInittouchState.wireVisible = this._currentDistanceMeasurementByMouse.wireVisible;
|
|
295
|
+
this._currentDistanceMeasurementByMouseInittouchState.targetVisible = this._currentDistanceMeasurementByMouse.targetVisible;
|
|
296
|
+
this._currentDistanceMeasurementByMouse.clickable = false;
|
|
297
|
+
this.fire("measurementStart", this._currentDistanceMeasurementByMouse);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
});
|
|
301
|
+
|
|
302
|
+
this._onMouseHoverOff = cameraControl.on("hoverOff", event => {
|
|
303
|
+
mouseHoverEntity = null;
|
|
304
|
+
|
|
305
|
+
this.markerDiv.style.marginLeft = `-100px`;
|
|
306
|
+
this.markerDiv.style.marginTop = `-100px`;
|
|
307
|
+
|
|
308
|
+
if (this._currentDistanceMeasurementByMouse) {
|
|
309
|
+
this._currentDistanceMeasurementByMouse.wireVisible = false;
|
|
310
|
+
this._currentDistanceMeasurementByMouse.targetVisible = false;
|
|
311
|
+
this._currentDistanceMeasurementByMouse.axisVisible = false;
|
|
312
|
+
}
|
|
313
|
+
canvas.style.cursor = "default";
|
|
314
|
+
});
|
|
315
|
+
|
|
316
|
+
this._onPickedNothing = cameraControl.on("pickedNothing", event => {
|
|
317
|
+
if (this._currentDistanceMeasurementByMouse) {
|
|
318
|
+
this.fire("measurementCancel", this._currentDistanceMeasurementByMouse);
|
|
319
|
+
this._currentDistanceMeasurementByMouse.destroy();
|
|
320
|
+
this._currentDistanceMeasurementByMouse = null;
|
|
321
|
+
}
|
|
322
|
+
startDot.setVisible(false);
|
|
323
|
+
touchState = FIRST_TOUCH_EXPECTED;
|
|
324
|
+
});
|
|
325
|
+
|
|
326
|
+
canvas.addEventListener("touchstart", this._onCanvasTouchStart = (event) => {
|
|
327
|
+
const touches = event.touches;
|
|
328
|
+
const changedTouches = event.changedTouches;
|
|
329
|
+
if (touches.length === 1 && changedTouches.length === 1) {
|
|
330
|
+
getCanvasPosFromEvent(touches[0], touchStartCanvasPos);
|
|
331
|
+
}
|
|
332
|
+
}, {passive: true});
|
|
333
|
+
|
|
334
|
+
canvas.addEventListener("touchend", this._onCanvasTouchEnd = (event) => {
|
|
335
|
+
const touches = event.touches;
|
|
336
|
+
const changedTouches = event.changedTouches;
|
|
337
|
+
if (touches.length === 0 && changedTouches.length === 1) {
|
|
338
|
+
getCanvasPosFromEvent(changedTouches[0], touchEndCanvasPos);
|
|
339
|
+
if (touchEndCanvasPos[0] > touchStartCanvasPos[0] + touchCanvasClickTolerance ||
|
|
340
|
+
touchEndCanvasPos[0] < touchStartCanvasPos[0] - touchCanvasClickTolerance ||
|
|
341
|
+
touchEndCanvasPos[1] > touchStartCanvasPos[1] + touchCanvasClickTolerance ||
|
|
342
|
+
touchEndCanvasPos[1] < touchStartCanvasPos[1] - touchCanvasClickTolerance) {
|
|
343
|
+
return; // User is repositioning the camera or model
|
|
344
|
+
}
|
|
345
|
+
const pickResult = scene.pick({
|
|
346
|
+
canvasPos: touchEndCanvasPos,
|
|
347
|
+
pickSurface: true,
|
|
348
|
+
pickSurfacePrecision: pickSurfacePrecisionEnabled
|
|
349
|
+
});
|
|
350
|
+
if (pickResult && pickResult.worldPos) {
|
|
351
|
+
switch (touchState) {
|
|
352
|
+
case FIRST_TOUCH_EXPECTED:
|
|
353
|
+
startDot.setVisible(true);
|
|
354
|
+
this._touchStartMarker.worldPos = pickResult.worldPos;
|
|
355
|
+
touchStartWorldPos.set(pickResult.worldPos);
|
|
356
|
+
touchState = SECOND_TOUCH_EXPECTED;
|
|
357
|
+
break;
|
|
358
|
+
case SECOND_TOUCH_EXPECTED:
|
|
359
|
+
startDot.setVisible(false);
|
|
360
|
+
this._touchStartMarker.worldPos = pickResult.worldPos;
|
|
361
|
+
const measurement = plugin.createMeasurement({
|
|
362
|
+
id: math.createUUID(),
|
|
363
|
+
origin: {
|
|
364
|
+
entity: mouseHoverEntity,
|
|
365
|
+
worldPos: touchStartWorldPos
|
|
366
|
+
},
|
|
367
|
+
target: {
|
|
368
|
+
entity: mouseHoverEntity,
|
|
369
|
+
worldPos: pickResult.worldPos
|
|
370
|
+
},
|
|
371
|
+
approximate: (!pickSurfacePrecisionEnabled)
|
|
372
|
+
});
|
|
373
|
+
measurement.clickable = true;
|
|
374
|
+
touchState = FIRST_TOUCH_EXPECTED;
|
|
375
|
+
this.fire("measurementEnd", measurement);
|
|
376
|
+
break;
|
|
377
|
+
}
|
|
378
|
+
} else {
|
|
379
|
+
startDot.setVisible(false);
|
|
380
|
+
touchState = FIRST_TOUCH_EXPECTED;
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
// event.stopPropagation();
|
|
384
|
+
}, {passive: true});
|
|
385
|
+
|
|
386
|
+
this._active = true;
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
/**
|
|
390
|
+
* Deactivates this DistanceMeasurementsControlLegacy, making it unresponsive to input.
|
|
391
|
+
*
|
|
392
|
+
* Destroys any {@link DistanceMeasurement} under construction.
|
|
393
|
+
*/
|
|
394
|
+
deactivate() {
|
|
395
|
+
|
|
396
|
+
if (!this._active) {
|
|
397
|
+
return;
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
this._touchStartDot.setVisible(false);
|
|
401
|
+
|
|
402
|
+
this.reset();
|
|
403
|
+
|
|
404
|
+
const input = this.plugin.viewer.scene.input;
|
|
405
|
+
input.off(this._onInputMouseDown);
|
|
406
|
+
input.off(this._onInputMouseUp);
|
|
407
|
+
|
|
408
|
+
const cameraControl = this.plugin.viewer.cameraControl;
|
|
409
|
+
cameraControl.off(this._onMouseHoverSurface);
|
|
410
|
+
cameraControl.off(this._onMouseHoverOff);
|
|
411
|
+
cameraControl.off(this._onPickedNothing);
|
|
412
|
+
|
|
413
|
+
const canvas = this.plugin.viewer.scene.canvas.canvas;
|
|
414
|
+
canvas.removeEventListener("touchstart", this._onCanvasTouchStart);
|
|
415
|
+
canvas.removeEventListener("touchend", this._onCanvasTouchEnd);
|
|
416
|
+
|
|
417
|
+
if (this._currentDistanceMeasurementByMouse) {
|
|
418
|
+
this.fire("measurementCancel", this._currentDistanceMeasurementByMouse);
|
|
419
|
+
this._currentDistanceMeasurementByMouse.destroy();
|
|
420
|
+
this._currentDistanceMeasurementByMouse = null;
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
this._active = false;
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
/**
|
|
427
|
+
* Resets this DistanceMeasurementsControlLegacy.
|
|
428
|
+
*
|
|
429
|
+
* Destroys any {@link DistanceMeasurement} under construction.
|
|
430
|
+
*
|
|
431
|
+
* Does nothing if the DistanceMeasurementsControlLegacy is not active.
|
|
432
|
+
*/
|
|
433
|
+
reset() {
|
|
434
|
+
if (!this._active) {
|
|
435
|
+
return;
|
|
436
|
+
}
|
|
437
|
+
if (this._currentDistanceMeasurementByMouse) {
|
|
438
|
+
this.fire("measurementCancel", this._currentDistanceMeasurementByMouse);
|
|
439
|
+
this._currentDistanceMeasurementByMouse.destroy();
|
|
440
|
+
this._currentDistanceMeasurementByMouse = null;
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
/**
|
|
445
|
+
* @private
|
|
446
|
+
*/
|
|
447
|
+
destroy() {
|
|
448
|
+
this._touchStartDot.destroy();
|
|
449
|
+
this.deactivate();
|
|
450
|
+
super.destroy();
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
const getCanvasPosFromEvent = function (event, canvasPos) {
|
|
455
|
+
if (!event) {
|
|
456
|
+
event = window.event;
|
|
457
|
+
canvasPos[0] = event.x;
|
|
458
|
+
canvasPos[1] = event.y;
|
|
459
|
+
} else {
|
|
460
|
+
let element = event.target;
|
|
461
|
+
let totalOffsetLeft = 0;
|
|
462
|
+
let totalOffsetTop = 0;
|
|
463
|
+
while (element.offsetParent) {
|
|
464
|
+
totalOffsetLeft += element.offsetLeft;
|
|
465
|
+
totalOffsetTop += element.offsetTop;
|
|
466
|
+
element = element.offsetParent;
|
|
467
|
+
}
|
|
468
|
+
canvasPos[0] = event.pageX - totalOffsetLeft;
|
|
469
|
+
canvasPos[1] = event.pageY - totalOffsetTop;
|
|
470
|
+
}
|
|
471
|
+
return canvasPos;
|
|
472
|
+
};
|
|
@@ -221,6 +221,46 @@ import {DistanceMeasurementsMouseControl} from "./DistanceMeasurementsMouseContr
|
|
|
221
221
|
* });
|
|
222
222
|
* });
|
|
223
223
|
* ````
|
|
224
|
+
*
|
|
225
|
+
* ## Example 5: Creating DistanceMeasurements with Touch Input
|
|
226
|
+
*
|
|
227
|
+
* In our fifth example, we'll show how to create distance measurements with touch input, with snapping
|
|
228
|
+
* to the nearest vertex or edge. While creating the measurements, a long-touch when setting the
|
|
229
|
+
* start or end point will cause the point to snap to the nearest vertex or edge. A quick
|
|
230
|
+
* touch-release will immediately set the point at the tapped position on the object surface.
|
|
231
|
+
*
|
|
232
|
+
* [[Run example](https://xeokit.github.io/xeokit-sdk/examples/measurement/#distance_createWithTouch_snapping)]
|
|
233
|
+
*
|
|
234
|
+
* ````javascript
|
|
235
|
+
* import {Viewer, XKTLoaderPlugin, DistanceMeasurementsPlugin, DistanceMeasurementsTouchControl} from "xeokit-sdk.es.js";
|
|
236
|
+
*
|
|
237
|
+
* const viewer = new Viewer({
|
|
238
|
+
* canvasId: "myCanvas",
|
|
239
|
+
* transparent: true
|
|
240
|
+
* });
|
|
241
|
+
*
|
|
242
|
+
* viewer.scene.camera.eye = [-2.37, 18.97, -26.12];
|
|
243
|
+
* viewer.scene.camera.look = [10.97, 5.82, -11.22];
|
|
244
|
+
* viewer.scene.camera.up = [0.36, 0.83, 0.40];
|
|
245
|
+
*
|
|
246
|
+
* const xktLoader = new XKTLoaderPlugin(viewer);
|
|
247
|
+
*
|
|
248
|
+
* const distanceMeasurements = new DistanceMeasurementsPlugin(viewer);
|
|
249
|
+
*
|
|
250
|
+
* const model = xktLoader.load({
|
|
251
|
+
* src: "./models/xkt/duplex/duplex.xkt"
|
|
252
|
+
* });
|
|
253
|
+
*
|
|
254
|
+
* const distanceMeasurements = new DistanceMeasurementsPlugin(viewer);
|
|
255
|
+
*
|
|
256
|
+
* const distanceMeasurementsTouchControl = new DistanceMeasurementsTouchControl(distanceMeasurements, {
|
|
257
|
+
* pointerLens : new PointerLens(viewer),
|
|
258
|
+
* snapToVertex: true,
|
|
259
|
+
* snapToEdge: true
|
|
260
|
+
* })
|
|
261
|
+
*
|
|
262
|
+
* distanceMeasurementsTouchControl.activate();
|
|
263
|
+
* ````
|
|
224
264
|
*/
|
|
225
265
|
class DistanceMeasurementsPlugin extends Plugin {
|
|
226
266
|
|
|
@@ -454,7 +494,7 @@ class DistanceMeasurementsPlugin extends Plugin {
|
|
|
454
494
|
}
|
|
455
495
|
|
|
456
496
|
/**
|
|
457
|
-
* Shows all or hides the
|
|
497
|
+
* Shows all or hides the distance label of each {@link DistanceMeasurement}.
|
|
458
498
|
*
|
|
459
499
|
* @param {Boolean} labelsShown Whether or not to show the labels.
|
|
460
500
|
*/
|