itowns 2.34.0 → 2.36.2

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.
Files changed (68) hide show
  1. package/CONTRIBUTORS.md +1 -0
  2. package/changelog.md +150 -0
  3. package/dist/debug.js +2 -16
  4. package/dist/debug.js.LICENSE.txt +6 -0
  5. package/dist/debug.js.map +1 -1
  6. package/dist/itowns.js +2 -19
  7. package/dist/itowns.js.LICENSE.txt +28 -0
  8. package/dist/itowns.js.map +1 -1
  9. package/examples/3dtiles_basic.html +2 -2
  10. package/examples/config.json +2 -1
  11. package/examples/js/plugins/CSVnVRTParser.js +0 -1
  12. package/examples/layers/JSONLayers/Administrative.json +1 -1
  13. package/examples/layers/JSONLayers/Cada.json +1 -1
  14. package/examples/layers/JSONLayers/EtatMajor.json +1 -1
  15. package/examples/layers/JSONLayers/IGN_MNT.json +1 -1
  16. package/examples/layers/JSONLayers/IGN_MNT_HIGHRES.json +1 -1
  17. package/examples/layers/JSONLayers/Ortho.json +1 -1
  18. package/examples/layers/JSONLayers/WORLD_DTM.json +1 -1
  19. package/examples/misc_camera_traveling.html +148 -0
  20. package/examples/misc_custom_label.html +0 -2
  21. package/examples/plugins_vrt.html +0 -1
  22. package/examples/source_file_geojson_raster.html +0 -3
  23. package/examples/source_file_shapefile.html +0 -1
  24. package/examples/source_stream_wfs_25d.html +8 -16
  25. package/examples/vector_tile_raster_2d.html +2 -2
  26. package/examples/vector_tile_raster_3d.html +2 -2
  27. package/examples/view_25d_map.html +28 -0
  28. package/examples/view_multi_25d.html +1 -1
  29. package/lib/Controls/FirstPersonControls.js +12 -14
  30. package/lib/Controls/FlyControls.js +2 -10
  31. package/lib/Controls/GlobeControls.js +231 -303
  32. package/lib/Controls/PlanarControls.js +5 -16
  33. package/lib/Controls/StateControl.js +362 -96
  34. package/lib/Converter/Feature2Mesh.js +20 -5
  35. package/lib/Converter/Feature2Texture.js +2 -2
  36. package/lib/Converter/convertToTile.js +1 -1
  37. package/lib/Core/AnimationPlayer.js +15 -0
  38. package/lib/Core/Feature.js +39 -38
  39. package/lib/Core/Geographic/Coordinates.js +56 -0
  40. package/lib/Core/Geographic/Crs.js +15 -0
  41. package/lib/Core/Geographic/Extent.js +99 -11
  42. package/lib/Core/Label.js +1 -1
  43. package/lib/Core/Math/Ellipsoid.js +26 -8
  44. package/lib/Core/Prefab/Globe/BuilderEllipsoidTile.js +1 -1
  45. package/lib/Core/Prefab/PlanarView.js +1 -1
  46. package/lib/Core/Style.js +1 -0
  47. package/lib/Core/TileMesh.js +3 -2
  48. package/lib/Core/View.js +3 -3
  49. package/lib/Layer/ElevationLayer.js +9 -16
  50. package/lib/Layer/LabelLayer.js +7 -1
  51. package/lib/Main.js +1 -1
  52. package/lib/Parser/ShapefileParser.js +1 -2
  53. package/lib/Parser/VectorTileParser.js +1 -1
  54. package/lib/Process/3dTilesProcessing.js +8 -8
  55. package/lib/Process/FeatureProcessing.js +1 -2
  56. package/lib/Process/ObjectRemovalHelper.js +5 -2
  57. package/lib/Renderer/Label2DRenderer.js +15 -11
  58. package/lib/Renderer/LayeredMaterial.js +2 -1
  59. package/lib/Renderer/OBB.js +2 -2
  60. package/lib/Renderer/RasterTile.js +22 -4
  61. package/lib/Renderer/Shader/ShaderChunk.js +3 -3
  62. package/lib/Renderer/c3DEngine.js +14 -2
  63. package/lib/Source/FileSource.js +2 -7
  64. package/lib/Source/VectorTilesSource.js +19 -0
  65. package/lib/ThreeExtended/loaders/GLTFLoader.js +320 -76
  66. package/lib/Utils/CameraUtils.js +8 -8
  67. package/lib/Utils/DEMUtils.js +2 -2
  68. package/package.json +29 -29
@@ -48,7 +48,13 @@ function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflec
48
48
  function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }
49
49
 
50
50
  // private members
51
- var EPS = 0.000001; // Orbit
51
+ var EPS = 0.000001;
52
+ var direction = {
53
+ up: new THREE.Vector2(0, 1),
54
+ bottom: new THREE.Vector2(0, -1),
55
+ left: new THREE.Vector2(1, 0),
56
+ right: new THREE.Vector2(-1, 0)
57
+ }; // Orbit
52
58
 
53
59
  var rotateStart = new THREE.Vector2();
54
60
  var rotateEnd = new THREE.Vector2();
@@ -102,8 +108,7 @@ var intersection = new THREE.Vector3(); // Set to true to enable target helper
102
108
 
103
109
  var enableTargetHelper = false;
104
110
  var helpers = {};
105
- // current downed key
106
- var currentKey;
111
+
107
112
  /**
108
113
  * Globe control pan event. Fires after camera pan
109
114
  * @event GlobeControls#pan-changed
@@ -150,7 +155,6 @@ var currentKey;
150
155
  * @property RANGE_CHANGED {string} Fires when camera's range to target change
151
156
  * @property CAMERA_TARGET_CHANGED {string} Fires when camera's target change
152
157
  */
153
-
154
158
  var CONTROL_EVENTS = {
155
159
  PAN_CHANGED: 'pan-changed',
156
160
  ORIENTATION_CHANGED: 'orientation-changed',
@@ -183,13 +187,12 @@ var previous;
183
187
  * @param {number} options.minDistance Minimum distance between ground and camera
184
188
  * @param {number} options.maxDistance Maximum distance between ground and camera
185
189
  * @param {bool} options.handleCollision enable collision camera with ground
186
- * @property {bool} enabled enable control
187
190
  * @property {number} minDistance Minimum distance between ground and camera
188
191
  * @property {number} maxDistance Maximum distance between ground and camera
189
192
  * @property {number} zoomSpeed Speed zoom with mouse
190
193
  * @property {number} rotateSpeed Speed camera rotation in orbit and panoramic mode
191
194
  * @property {number} minDistanceCollision Minimum distance collision between ground and camera
192
- * @property {bool} enableDamping enable camera damping, if it's disabled the camera immediately when the mouse button is released.
195
+ * @property {boolean} enableDamping enable camera damping, if it's disabled the camera immediately when the mouse button is released.
193
196
  * If it's enabled, the camera movement is decelerate.
194
197
  */
195
198
 
@@ -208,10 +211,17 @@ var GlobeControls = /*#__PURE__*/function (_THREE$EventDispatche) {
208
211
  _this.view = view;
209
212
  _this.camera = view.camera.camera3D; // State control
210
213
 
211
- _this.states = new _StateControl["default"](_this.view);
212
- _this.state = _this.states.NONE; // Set to false to disable this control
214
+ _this.states = new _StateControl["default"](_this.view); // this.enabled property has moved to StateControl
213
215
 
214
- _this.enabled = true; // These options actually enables dollying in and out; left as "zoom" for
216
+ Object.defineProperty((0, _assertThisInitialized2["default"])(_this), 'enabled', {
217
+ get: function get() {
218
+ return _this.states.enabled;
219
+ },
220
+ set: function set(value) {
221
+ console.warn('GlobeControls.enabled property is deprecated. Use StateControl.enabled instead ' + '- which you can access with GlobeControls.states.enabled.');
222
+ _this.states.enabled = value;
223
+ }
224
+ }); // These options actually enables dollying in and out; left as "zoom" for
215
225
  // backwards compatibility
216
226
 
217
227
  if (options.zoomSpeed) {
@@ -246,9 +256,17 @@ var GlobeControls = /*#__PURE__*/function (_THREE$EventDispatche) {
246
256
  // Set collision options
247
257
 
248
258
  _this.handleCollision = typeof options.handleCollision !== 'undefined' ? options.handleCollision : true;
249
- _this.minDistanceCollision = 60; // Set to true to disable use of the keys
250
-
251
- _this.enableKeys = true; // Enable Damping
259
+ _this.minDistanceCollision = 60; // this.enableKeys property has moved to StateControl
260
+
261
+ Object.defineProperty((0, _assertThisInitialized2["default"])(_this), 'enableKeys', {
262
+ get: function get() {
263
+ return _this.states.enableKeys;
264
+ },
265
+ set: function set(value) {
266
+ console.warn('GlobeControls.enableKeys property is deprecated. Use StateControl.enableKeys instead ' + '- which you can access with GlobeControls.states.enableKeys.');
267
+ _this.states.enableKeys = value;
268
+ }
269
+ }); // Enable Damping
252
270
 
253
271
  _this.enableDamping = true;
254
272
  _this.dampingMoveFactor = options.dampingMoveFactor != undefined ? options.dampingMoveFactor : dampingFactorDefault;
@@ -264,46 +282,42 @@ var GlobeControls = /*#__PURE__*/function (_THREE$EventDispatche) {
264
282
  view.notifyChange(_this.camera);
265
283
  } : function () {};
266
284
  _this._onEndingMove = null;
267
- _this._onMouseMove = _this.onMouseMove.bind((0, _assertThisInitialized2["default"])(_this));
268
- _this._onMouseUp = _this.onMouseUp.bind((0, _assertThisInitialized2["default"])(_this));
269
- _this._onMouseDown = _this.onMouseDown.bind((0, _assertThisInitialized2["default"])(_this));
270
- _this._onMouseWheel = _this.onMouseWheel.bind((0, _assertThisInitialized2["default"])(_this));
271
- _this._onContextMenuListener = _this.onContextMenuListener.bind((0, _assertThisInitialized2["default"])(_this));
272
285
  _this._onTravel = _this.travel.bind((0, _assertThisInitialized2["default"])(_this));
273
286
  _this._onTouchStart = _this.onTouchStart.bind((0, _assertThisInitialized2["default"])(_this));
274
- _this._update = _this.update.bind((0, _assertThisInitialized2["default"])(_this));
287
+ _this._onTouchEnd = _this.onTouchEnd.bind((0, _assertThisInitialized2["default"])(_this));
275
288
  _this._onTouchMove = _this.onTouchMove.bind((0, _assertThisInitialized2["default"])(_this));
276
- _this._onKeyDown = _this.onKeyDown.bind((0, _assertThisInitialized2["default"])(_this));
277
- _this._onKeyUp = _this.onKeyUp.bind((0, _assertThisInitialized2["default"])(_this));
278
- _this._onBlurListener = _this.onBlurListener.bind((0, _assertThisInitialized2["default"])(_this));
279
-
280
- _this.view.domElement.addEventListener('contextmenu', _this._onContextMenuListener, false);
281
-
282
- _this.view.domElement.addEventListener('mousedown', _this._onMouseDown, false);
289
+ _this._onStateChange = _this.onStateChange.bind((0, _assertThisInitialized2["default"])(_this));
290
+ _this._onRotation = _this.handleRotation.bind((0, _assertThisInitialized2["default"])(_this));
291
+ _this._onDrag = _this.handleDrag.bind((0, _assertThisInitialized2["default"])(_this));
292
+ _this._onDolly = _this.handleDolly.bind((0, _assertThisInitialized2["default"])(_this));
293
+ _this._onPan = _this.handlePan.bind((0, _assertThisInitialized2["default"])(_this));
294
+ _this._onPanoramic = _this.handlePanoramic.bind((0, _assertThisInitialized2["default"])(_this));
295
+ _this._onZoom = _this.handleZoom.bind((0, _assertThisInitialized2["default"])(_this));
283
296
 
284
- _this.view.domElement.addEventListener('mousewheel', _this._onMouseWheel, false);
297
+ _this.states.addEventListener('state-changed', _this._onStateChange, false);
285
298
 
286
- _this.view.domElement.addEventListener('DOMMouseScroll', _this._onMouseWheel, false); // firefox
299
+ _this.states.addEventListener(_this.states.ORBIT._event, _this._onRotation, false);
287
300
 
301
+ _this.states.addEventListener(_this.states.MOVE_GLOBE._event, _this._onDrag, false);
288
302
 
289
- _this.view.domElement.addEventListener('touchstart', _this._onTouchStart, false);
303
+ _this.states.addEventListener(_this.states.DOLLY._event, _this._onDolly, false);
290
304
 
291
- _this.view.domElement.addEventListener('touchend', _this._onMouseUp, false);
305
+ _this.states.addEventListener(_this.states.PAN._event, _this._onPan, false);
292
306
 
293
- _this.view.domElement.addEventListener('touchmove', _this._onTouchMove, false);
307
+ _this.states.addEventListener(_this.states.PANORAMIC._event, _this._onPanoramic, false);
294
308
 
295
- _this.states.addEventListener('travel_in', _this._onTravel, false);
309
+ _this.states.addEventListener('zoom', _this._onZoom, false);
296
310
 
297
- _this.states.addEventListener('travel_out', _this._onTravel, false); // refresh control for each animation's frame
311
+ _this.view.domElement.addEventListener('touchstart', _this._onTouchStart, false);
298
312
 
313
+ _this.view.domElement.addEventListener('touchend', _this._onTouchEnd, false);
299
314
 
300
- _this.player.addEventListener('animation-frame', _this._update); // TODO: Why windows
315
+ _this.view.domElement.addEventListener('touchmove', _this._onTouchMove, false);
301
316
 
317
+ _this.states.addEventListener(_this.states.TRAVEL_IN._event, _this._onTravel, false);
302
318
 
303
- window.addEventListener('keydown', _this._onKeyDown, false);
304
- window.addEventListener('keyup', _this._onKeyUp, false); // Reset key/mouse when window loose focus
319
+ _this.states.addEventListener(_this.states.TRAVEL_OUT._event, _this._onTravel, false);
305
320
 
306
- window.addEventListener('blur', _this._onBlurListener);
307
321
  view.scene.add(cameraTarget);
308
322
 
309
323
  if (enableTargetHelper) {
@@ -344,7 +358,8 @@ var GlobeControls = /*#__PURE__*/function (_THREE$EventDispatche) {
344
358
  }, {
345
359
  key: "isPaused",
346
360
  get: function get() {
347
- return this.state == this.states.NONE;
361
+ // TODO : also check if CameraUtils is performing an animation
362
+ return this.states.currentState === this.states.NONE && !this.player.isPlaying();
348
363
  }
349
364
  }, {
350
365
  key: "onEndingMove",
@@ -354,7 +369,6 @@ var GlobeControls = /*#__PURE__*/function (_THREE$EventDispatche) {
354
369
  this._onEndingMove = null;
355
370
  }
356
371
 
357
- this.state = this.states.NONE;
358
372
  this.handlingEvent(current);
359
373
  }
360
374
  }, {
@@ -395,7 +409,6 @@ var GlobeControls = /*#__PURE__*/function (_THREE$EventDispatche) {
395
409
  key: "mouseToPan",
396
410
  value: function mouseToPan(deltaX, deltaY) {
397
411
  var gfx = this.view.mainLoop.gfxEngine;
398
- this.state = this.states.PAN;
399
412
 
400
413
  if (this.camera.isPerspectiveCamera) {
401
414
  var targetDistance = this.camera.position.distanceTo(this.getCameraTargetPosition()); // half of the fov is center to top of screen
@@ -443,6 +456,9 @@ var GlobeControls = /*#__PURE__*/function (_THREE$EventDispatche) {
443
456
  }, {
444
457
  key: "update",
445
458
  value: function update() {
459
+ var _this2 = this;
460
+
461
+ var state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.states.currentState;
446
462
  // We compute distance between camera's bounding sphere and geometry's obb up face
447
463
  minDistanceZ = Infinity;
448
464
 
@@ -469,7 +485,7 @@ var GlobeControls = /*#__PURE__*/function (_THREE$EventDispatche) {
469
485
  }
470
486
  }
471
487
 
472
- switch (this.state) {
488
+ switch (state) {
473
489
  // MOVE_GLOBE Rotate globe with mouse
474
490
  case this.states.MOVE_GLOBE:
475
491
  if (minDistanceZ < 0) {
@@ -588,89 +604,166 @@ var GlobeControls = /*#__PURE__*/function (_THREE$EventDispatche) {
588
604
  } // Launch animationdamping if mouse stops these movements
589
605
 
590
606
 
591
- if (this.enableDamping && this.state === this.states.ORBIT && this.player.isStopped() && (sphericalDelta.theta > EPS || sphericalDelta.phi > EPS)) {
607
+ if (this.enableDamping && state === this.states.ORBIT && this.player.isStopped() && (sphericalDelta.theta > EPS || sphericalDelta.phi > EPS)) {
608
+ this.player.setCallback(function () {
609
+ _this2.update(_this2.states.ORBIT);
610
+ });
592
611
  this.player.playLater(durationDampingOrbital, 2);
593
612
  }
594
613
  }
595
614
  }, {
596
- key: "onMouseMove",
597
- value: function onMouseMove(event) {
598
- if (this.player.isPlaying()) {
599
- this.player.stop();
600
- }
601
-
602
- if (this.enabled === false) {
615
+ key: "onStateChange",
616
+ value: function onStateChange(event) {
617
+ // If the state changed to NONE, end the movement associated to the previous state.
618
+ if (this.states.currentState === this.states.NONE) {
619
+ this.handleEndMovement(event);
603
620
  return;
604
- }
621
+ } // Stop CameraUtils ongoing animations, which can for instance be triggered with `this.travel` or
622
+ // `this.lookAtCoordinate` methods.
605
623
 
606
- event.preventDefault();
607
- var coords = this.view.eventToViewCoords(event);
608
624
 
609
- switch (this.state) {
610
- case this.states.ORBIT:
611
- case this.states.PANORAMIC:
612
- {
613
- rotateEnd.copy(coords);
614
- rotateDelta.subVectors(rotateEnd, rotateStart);
615
- var gfx = this.view.mainLoop.gfxEngine;
616
- this.rotateLeft(2 * Math.PI * rotateDelta.x / gfx.width * this.rotateSpeed); // rotating up and down along whole screen attempts to go 360, but limited to 180
625
+ _CameraUtils["default"].stop(this.view, this.camera); // Dispatch events which specify if changes occurred in camera transform options.
617
626
 
618
- this.rotateUp(2 * Math.PI * rotateDelta.y / gfx.height * this.rotateSpeed);
619
- rotateStart.copy(rotateEnd);
620
- break;
621
- }
622
627
 
623
- case this.states.DOLLY:
624
- dollyEnd.copy(coords);
625
- dollyDelta.subVectors(dollyEnd, dollyStart);
626
- this.dolly(-dollyDelta.y);
627
- dollyStart.copy(dollyEnd);
628
- break;
628
+ this.onEndingMove(); // Stop eventual damping movement.
629
629
 
630
- case this.states.PAN:
631
- panEnd.copy(coords);
632
- panDelta.subVectors(panEnd, panStart);
633
- this.mouseToPan(panDelta.x, panDelta.y);
634
- panStart.copy(panEnd);
635
- break;
630
+ this.player.stop(); // Update camera transform options.
636
631
 
637
- case this.states.MOVE_GLOBE:
638
- {
639
- var normalized = this.view.viewToNormalizedCoords(coords);
640
- raycaster.setFromCamera(normalized, this.camera); // If there's intersection then move globe else we stop the move
632
+ this.updateTarget();
633
+ previous = _CameraUtils["default"].getTransformCameraLookingAtTarget(this.view, this.camera, pickedPosition); // Initialize rotation and panoramic movements.
641
634
 
642
- if (raycaster.ray.intersectSphere(pickSphere, intersection)) {
643
- normalizedIntersection.copy(intersection).normalize();
644
- moveAroundGlobe.setFromUnitVectors(normalizedIntersection, lastNormalizedIntersection);
645
- lastTimeMouseMove = Date.now();
646
- } else {
647
- this.onMouseUp();
648
- }
635
+ rotateStart.copy(event.viewCoords); // Initialize drag movement.
649
636
 
650
- break;
651
- }
637
+ if (this.view.getPickingPositionFromDepth(event.viewCoords, pickingPoint)) {
638
+ pickSphere.radius = pickingPoint.length();
639
+ lastNormalizedIntersection.copy(pickingPoint).normalize();
640
+ this.updateHelper(pickingPoint, helpers.picking);
641
+ } // Initialize dolly movement.
652
642
 
653
- default:
654
- }
655
643
 
656
- if (this.state !== this.states.NONE) {
644
+ dollyStart.copy(event.viewCoords); // Initialize pan movement.
645
+
646
+ panStart.copy(event.viewCoords);
647
+ }
648
+ }, {
649
+ key: "handleRotation",
650
+ value: function handleRotation(event) {
651
+ // Stop player if needed. Player can be playing while moving mouse in the case of rotation. This is due to the
652
+ // fact that a damping move can occur while rotating (without the need of releasing the mouse button)
653
+ this.player.stop();
654
+ this.handlePanoramic(event);
655
+ }
656
+ }, {
657
+ key: "handleDrag",
658
+ value: function handleDrag(event) {
659
+ var normalized = this.view.viewToNormalizedCoords(event.viewCoords); // An updateMatrixWorld on the camera prevents camera jittering when moving globe on a zoomed out view, with
660
+ // devtools open in web browser.
661
+
662
+ this.camera.updateMatrixWorld();
663
+ raycaster.setFromCamera(normalized, this.camera); // If there's intersection then move globe else we stop the move
664
+
665
+ if (raycaster.ray.intersectSphere(pickSphere, intersection)) {
666
+ normalizedIntersection.copy(intersection).normalize();
667
+ moveAroundGlobe.setFromUnitVectors(normalizedIntersection, lastNormalizedIntersection);
668
+ lastTimeMouseMove = Date.now();
657
669
  this.update();
670
+ } else {
671
+ this.states.onPointerUp();
672
+ }
673
+ }
674
+ }, {
675
+ key: "handleDolly",
676
+ value: function handleDolly(event) {
677
+ dollyEnd.copy(event.viewCoords);
678
+ dollyDelta.subVectors(dollyEnd, dollyStart);
679
+ this.dolly(-dollyDelta.y);
680
+ dollyStart.copy(dollyEnd);
681
+ this.update();
682
+ }
683
+ }, {
684
+ key: "handlePan",
685
+ value: function handlePan(event) {
686
+ if (event.viewCoords) {
687
+ panEnd.copy(event.viewCoords);
688
+ panDelta.subVectors(panEnd, panStart);
689
+ panStart.copy(panEnd);
690
+ } else if (event.direction) {
691
+ panDelta.copy(direction[event.direction]).multiplyScalar(this.keyPanSpeed);
692
+ }
693
+
694
+ this.mouseToPan(panDelta.x, panDelta.y);
695
+ this.update(this.states.PAN);
696
+ }
697
+ }, {
698
+ key: "handlePanoramic",
699
+ value: function handlePanoramic(event) {
700
+ rotateEnd.copy(event.viewCoords);
701
+ rotateDelta.subVectors(rotateEnd, rotateStart);
702
+ var gfx = this.view.mainLoop.gfxEngine;
703
+ sphericalDelta.theta -= 2 * Math.PI * rotateDelta.x / gfx.width * this.rotateSpeed; // rotating up and down along whole screen attempts to go 360, but limited to 180
704
+
705
+ sphericalDelta.phi -= 2 * Math.PI * rotateDelta.y / gfx.height * this.rotateSpeed;
706
+ rotateStart.copy(rotateEnd);
707
+ this.update();
708
+ }
709
+ }, {
710
+ key: "handleEndMovement",
711
+ value: function handleEndMovement() {
712
+ var _this3 = this;
713
+
714
+ var event = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
715
+ this.dispatchEvent(this.endEvent);
716
+ this.player.stop(); // Launch damping movement for :
717
+ // * this.states.ORBIT
718
+ // * this.states.MOVE_GLOBE
719
+
720
+ if (this.enableDamping) {
721
+ if (event.previous === this.states.ORBIT && (sphericalDelta.theta > EPS || sphericalDelta.phi > EPS)) {
722
+ this.player.setCallback(function () {
723
+ _this3.update(_this3.states.ORBIT);
724
+ });
725
+ this.player.play(durationDampingOrbital);
726
+
727
+ this._onEndingMove = function () {
728
+ return _this3.onEndingMove();
729
+ };
730
+
731
+ this.player.addEventListener('animation-stopped', this._onEndingMove);
732
+ } else if (event.previous === this.states.MOVE_GLOBE && Date.now() - lastTimeMouseMove < 50) {
733
+ this.player.setCallback(function () {
734
+ _this3.update(_this3.states.MOVE_GLOBE);
735
+ }); // animation since mouse up event occurs less than 50ms after the last mouse move
736
+
737
+ this.player.play(durationDampingMove);
738
+
739
+ this._onEndingMove = function () {
740
+ return _this3.onEndingMove();
741
+ };
742
+
743
+ this.player.addEventListener('animation-stopped', this._onEndingMove);
744
+ } else {
745
+ this.onEndingMove();
746
+ }
747
+ } else {
748
+ this.onEndingMove();
658
749
  }
659
750
  }
660
751
  }, {
661
752
  key: "updateTarget",
662
753
  value: function updateTarget() {
663
- // Update camera's target position
664
- this.view.getPickingPositionFromDepth(null, pickedPosition);
665
- var distance = !isNaN(pickedPosition.x) ? this.camera.position.distanceTo(pickedPosition) : 100;
666
- targetPosition.set(0, 0, -distance);
667
- this.camera.localToWorld(targetPosition); // set new camera target on globe
668
-
669
- positionObject(targetPosition, cameraTarget);
670
- cameraTarget.matrixWorldInverse.copy(cameraTarget.matrixWorld).invert();
671
- targetPosition.copy(this.camera.position);
672
- targetPosition.applyMatrix4(cameraTarget.matrixWorldInverse);
673
- spherical.setFromVector3(targetPosition);
754
+ // Check if the middle of the screen is on the globe (to prevent having a dark-screen bug if outside the globe)
755
+ if (this.view.getPickingPositionFromDepth(null, pickedPosition)) {
756
+ // Update camera's target position
757
+ var distance = !isNaN(pickedPosition.x) ? this.camera.position.distanceTo(pickedPosition) : 100;
758
+ targetPosition.set(0, 0, -distance);
759
+ this.camera.localToWorld(targetPosition); // set new camera target on globe
760
+
761
+ positionObject(targetPosition, cameraTarget);
762
+ cameraTarget.matrixWorldInverse.copy(cameraTarget.matrixWorld).invert();
763
+ targetPosition.copy(this.camera.position);
764
+ targetPosition.applyMatrix4(cameraTarget.matrixWorldInverse);
765
+ spherical.setFromVector3(targetPosition);
766
+ }
674
767
  }
675
768
  }, {
676
769
  key: "handlingEvent",
@@ -721,68 +814,9 @@ var GlobeControls = /*#__PURE__*/function (_THREE$EventDispatche) {
721
814
  }
722
815
  }
723
816
  }
724
- }, {
725
- key: "onMouseDown",
726
- value: function onMouseDown(event) {
727
- _CameraUtils["default"].stop(this.view, this.camera);
728
-
729
- this.player.stop();
730
- this.onEndingMove();
731
-
732
- if (this.enabled === false) {
733
- return;
734
- }
735
-
736
- this.updateTarget();
737
- previous = _CameraUtils["default"].getTransformCameraLookingAtTarget(this.view, this.camera, pickedPosition);
738
- this.state = this.states.inputToState(event.button, currentKey);
739
- var coords = this.view.eventToViewCoords(event);
740
-
741
- switch (this.state) {
742
- case this.states.ORBIT:
743
- case this.states.PANORAMIC:
744
- rotateStart.copy(coords);
745
- break;
746
-
747
- case this.states.MOVE_GLOBE:
748
- {
749
- // update picking on sphere
750
- if (this.view.getPickingPositionFromDepth(coords, pickingPoint)) {
751
- pickSphere.radius = pickingPoint.length();
752
- lastNormalizedIntersection.copy(pickingPoint).normalize();
753
- this.updateHelper(pickingPoint, helpers.picking);
754
- } else {
755
- this.state = this.states.NONE;
756
- }
757
-
758
- break;
759
- }
760
-
761
- case this.states.DOLLY:
762
- dollyStart.copy(coords);
763
- break;
764
-
765
- case this.states.PAN:
766
- panStart.copy(coords);
767
- break;
768
-
769
- default:
770
- }
771
-
772
- if (this.state != this.states.NONE) {
773
- this.view.domElement.addEventListener('mousemove', this._onMouseMove, false);
774
- this.view.domElement.addEventListener('mouseup', this._onMouseUp, false);
775
- this.view.domElement.addEventListener('mouseleave', this._onMouseUp, false);
776
- this.dispatchEvent(this.startEvent);
777
- }
778
- }
779
817
  }, {
780
818
  key: "travel",
781
819
  value: function travel(event) {
782
- if (this.enabled === false) {
783
- return;
784
- }
785
-
786
820
  this.player.stop();
787
821
  var point = this.view.getPickingPositionFromDepth(event.viewCoords);
788
822
  var range = this.getRange(point);
@@ -790,74 +824,20 @@ var GlobeControls = /*#__PURE__*/function (_THREE$EventDispatche) {
790
824
  if (point && range > this.minDistance) {
791
825
  return this.lookAtCoordinate({
792
826
  coord: new _Coordinates["default"]('EPSG:4978', point),
793
- range: range * (event.type === 'travel_out' ? 1 / 0.6 : 0.6),
827
+ range: range * (event.direction === 'out' ? 1 / 0.6 : 0.6),
794
828
  time: 1500
795
829
  });
796
830
  }
797
831
  }
798
832
  }, {
799
- key: "onMouseUp",
800
- value: function onMouseUp() {
801
- var _this2 = this;
802
-
803
- if (this.enabled === false) {
804
- return;
805
- }
806
-
807
- this.view.domElement.removeEventListener('mousemove', this._onMouseMove, false);
808
- this.view.domElement.removeEventListener('mouseup', this._onMouseUp, false);
809
- this.view.domElement.removeEventListener('mouseleave', this._onMouseUp, false);
810
- this.dispatchEvent(this.endEvent);
811
- this.player.stop(); // Launch damping movement for :
812
- // * this.states.ORBIT
813
- // * this.states.MOVE_GLOBE
814
-
815
- if (this.enableDamping) {
816
- if (this.state === this.states.ORBIT && (sphericalDelta.theta > EPS || sphericalDelta.phi > EPS)) {
817
- this.player.play(durationDampingOrbital);
818
-
819
- this._onEndingMove = function () {
820
- return _this2.onEndingMove();
821
- };
822
-
823
- this.player.addEventListener('animation-stopped', this._onEndingMove);
824
- } else if (this.state === this.states.MOVE_GLOBE && Date.now() - lastTimeMouseMove < 50) {
825
- // animation since mouse up event occurs less than 50ms after the last mouse move
826
- this.player.play(durationDampingMove);
827
-
828
- this._onEndingMove = function () {
829
- return _this2.onEndingMove();
830
- };
831
-
832
- this.player.addEventListener('animation-stopped', this._onEndingMove);
833
- } else {
834
- this.onEndingMove();
835
- }
836
- } else {
837
- this.onEndingMove();
838
- }
839
- }
840
- }, {
841
- key: "onMouseWheel",
842
- value: function onMouseWheel(event) {
833
+ key: "handleZoom",
834
+ value: function handleZoom(event) {
843
835
  this.player.stop();
844
836
 
845
- if (!this.enabled || !this.states.DOLLY.enable) {
846
- return;
847
- }
848
-
849
837
  _CameraUtils["default"].stop(this.view, this.camera);
850
838
 
851
- event.preventDefault();
852
839
  this.updateTarget();
853
- var delta = 0; // WebKit / Opera / Explorer 9
854
-
855
- if (event.wheelDelta !== undefined) {
856
- delta = event.wheelDelta; // Firefox
857
- } else if (event.detail !== undefined) {
858
- delta = -event.detail;
859
- }
860
-
840
+ var delta = -event.delta;
861
841
  this.dolly(delta);
862
842
  var previousRange = this.getRange(pickedPosition);
863
843
  this.update();
@@ -874,61 +854,13 @@ var GlobeControls = /*#__PURE__*/function (_THREE$EventDispatche) {
874
854
  this.dispatchEvent(this.startEvent);
875
855
  this.dispatchEvent(this.endEvent);
876
856
  }
877
- }, {
878
- key: "onKeyUp",
879
- value: function onKeyUp() {
880
- if (this.enabled === false || this.enableKeys === false) {
881
- return;
882
- }
883
-
884
- currentKey = undefined;
885
- }
886
- }, {
887
- key: "onKeyDown",
888
- value: function onKeyDown(event) {
889
- this.player.stop();
890
-
891
- if (this.enabled === false || this.enableKeys === false) {
892
- return;
893
- }
894
-
895
- currentKey = event.keyCode;
896
-
897
- switch (event.keyCode) {
898
- case this.states.PAN.up:
899
- this.mouseToPan(0, this.keyPanSpeed);
900
- this.state = this.states.PAN;
901
- this.update();
902
- break;
903
-
904
- case this.states.PAN.bottom:
905
- this.mouseToPan(0, -this.keyPanSpeed);
906
- this.state = this.states.PAN;
907
- this.update();
908
- break;
909
-
910
- case this.states.PAN.left:
911
- this.mouseToPan(this.keyPanSpeed, 0);
912
- this.state = this.states.PAN;
913
- this.update();
914
- break;
915
-
916
- case this.states.PAN.right:
917
- this.mouseToPan(-this.keyPanSpeed, 0);
918
- this.state = this.states.PAN;
919
- this.update();
920
- break;
921
-
922
- default:
923
- }
924
- }
925
857
  }, {
926
858
  key: "onTouchStart",
927
859
  value: function onTouchStart(event) {
928
860
  // CameraUtils.stop(view);
929
- this.player.stop();
861
+ this.player.stop(); // TODO : this.states.enabled check should be removed when moving touch events management to StateControl
930
862
 
931
- if (this.enabled === false) {
863
+ if (this.states.enabled === false) {
932
864
  return;
933
865
  }
934
866
 
@@ -980,9 +912,10 @@ var GlobeControls = /*#__PURE__*/function (_THREE$EventDispatche) {
980
912
  value: function onTouchMove(event) {
981
913
  if (this.player.isPlaying()) {
982
914
  this.player.stop();
983
- }
915
+ } // TODO : this.states.enabled check should be removed when moving touch events management to StateControl
916
+
984
917
 
985
- if (this.enabled === false) {
918
+ if (this.states.enabled === false) {
986
919
  return;
987
920
  }
988
921
 
@@ -993,7 +926,10 @@ var GlobeControls = /*#__PURE__*/function (_THREE$EventDispatche) {
993
926
  case this.states.MOVE_GLOBE.finger:
994
927
  {
995
928
  var coords = this.view.eventToViewCoords(event);
996
- var normalized = this.view.viewToNormalizedCoords(coords);
929
+ var normalized = this.view.viewToNormalizedCoords(coords); // An updateMatrixWorld on the camera prevents camera jittering when moving globe on a zoomed out view, with
930
+ // devtools open in web browser.
931
+
932
+ this.camera.updateMatrixWorld();
997
933
  raycaster.setFromCamera(normalized, this.camera); // If there's intersection then move globe else we stop the move
998
934
 
999
935
  if (raycaster.ray.intersectSphere(pickSphere, intersection)) {
@@ -1001,7 +937,7 @@ var GlobeControls = /*#__PURE__*/function (_THREE$EventDispatche) {
1001
937
  moveAroundGlobe.setFromUnitVectors(normalizedIntersection, lastNormalizedIntersection);
1002
938
  lastTimeMouseMove = Date.now();
1003
939
  } else {
1004
- this.onMouseUp.bind(this)();
940
+ this.onTouchEnd();
1005
941
  }
1006
942
 
1007
943
  break;
@@ -1040,41 +976,33 @@ var GlobeControls = /*#__PURE__*/function (_THREE$EventDispatche) {
1040
976
  }
1041
977
 
1042
978
  if (this.state !== this.states.NONE) {
1043
- this.update();
979
+ this.update(this.state);
1044
980
  }
1045
981
  }
1046
982
  }, {
1047
- key: "onContextMenuListener",
1048
- value: function onContextMenuListener(event) {
1049
- event.preventDefault();
1050
- }
1051
- }, {
1052
- key: "onBlurListener",
1053
- value: function onBlurListener() {
1054
- this.onKeyUp();
1055
- this.onMouseUp();
983
+ key: "onTouchEnd",
984
+ value: function onTouchEnd() {
985
+ this.handleEndMovement({
986
+ previous: this.state
987
+ });
988
+ this.state = this.states.NONE;
1056
989
  }
1057
990
  }, {
1058
991
  key: "dispose",
1059
992
  value: function dispose() {
1060
- this.view.domElement.removeEventListener('contextmenu', this._onContextMenuListener, false);
1061
- this.view.domElement.removeEventListener('mousedown', this._onMouseDown, false);
1062
- this.view.domElement.removeEventListener('mousemove', this._onMouseMove, false);
1063
- this.view.domElement.removeEventListener('mousewheel', this._onMouseWheel, false);
1064
- this.view.domElement.removeEventListener('DOMMouseScroll', this._onMouseWheel, false); // firefox
1065
-
1066
- this.view.domElement.removeEventListener('mouseup', this._onMouseUp, false);
1067
- this.view.domElement.removeEventListener('mouseleave', this._onMouseUp, false);
1068
993
  this.view.domElement.removeEventListener('touchstart', this._onTouchStart, false);
1069
- this.view.domElement.removeEventListener('touchend', this._onMouseUp, false);
994
+ this.view.domElement.removeEventListener('touchend', this._onTouchEnd, false);
1070
995
  this.view.domElement.removeEventListener('touchmove', this._onTouchMove, false);
1071
996
  this.states.dispose();
1072
- this.states.removeEventListener('travel_in', this._onTravel, false);
1073
- this.states.removeEventListener('travel_out', this._onTravel, false);
1074
- this.player.removeEventListener('animation-frame', this._onKeyUp);
1075
- window.removeEventListener('keydown', this._onKeyDown, false);
1076
- window.removeEventListener('keyup', this._onKeyUp, false);
1077
- window.removeEventListener('blur', this._onBlurListener);
997
+ this.states.removeEventListener('state-changed', this._onStateChange, false);
998
+ this.states.removeEventListener(this.states.ORBIT._event, this._onRotation, false);
999
+ this.states.removeEventListener(this.states.MOVE_GLOBE._event, this._onDrag, false);
1000
+ this.states.removeEventListener(this.states.DOLLY._event, this._onDolly, false);
1001
+ this.states.removeEventListener(this.states.PAN._event, this._onPan, false);
1002
+ this.states.removeEventListener(this.states.PANORAMIC._event, this._onPanoramic, false);
1003
+ this.states.removeEventListener('zoom', this._onZoom, false);
1004
+ this.states.removeEventListener(this.states.TRAVEL_IN._event, this._onTravel, false);
1005
+ this.states.removeEventListener(this.states.TRAVEL_OUT._event, this._onTravel, false);
1078
1006
  this.dispatchEvent({
1079
1007
  type: 'dispose'
1080
1008
  });
@@ -1178,7 +1106,7 @@ var GlobeControls = /*#__PURE__*/function (_THREE$EventDispatche) {
1178
1106
  key: "pan",
1179
1107
  value: function pan(pVector) {
1180
1108
  this.mouseToPan(pVector.x, pVector.y);
1181
- this.update();
1109
+ this.update(this.states.PAN);
1182
1110
  return Promise.resolve();
1183
1111
  }
1184
1112
  /**
@@ -1368,7 +1296,7 @@ var GlobeControls = /*#__PURE__*/function (_THREE$EventDispatche) {
1368
1296
  }, {
1369
1297
  key: "lookAtCoordinate",
1370
1298
  value: function lookAtCoordinate() {
1371
- var _this3 = this;
1299
+ var _this4 = this;
1372
1300
 
1373
1301
  var params = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
1374
1302
  var isAnimated = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.isAnimationEnabled();
@@ -1409,11 +1337,11 @@ var GlobeControls = /*#__PURE__*/function (_THREE$EventDispatche) {
1409
1337
  type: 'animation-started'
1410
1338
  });
1411
1339
  return _CameraUtils["default"].animateCameraToLookAtTarget(this.view, this.camera, params).then(function (result) {
1412
- _this3.dispatchEvent({
1340
+ _this4.dispatchEvent({
1413
1341
  type: 'animation-ended'
1414
1342
  });
1415
1343
 
1416
- _this3.handlingEvent(result);
1344
+ _this4.handlingEvent(result);
1417
1345
 
1418
1346
  return result;
1419
1347
  });
@@ -1421,7 +1349,7 @@ var GlobeControls = /*#__PURE__*/function (_THREE$EventDispatche) {
1421
1349
  return _CameraUtils["default"].transformCameraToLookAtTarget(this.view, this.camera, params).then(function (result) {
1422
1350
  cameraTarget.position.copy(result.targetWorldPosition);
1423
1351
 
1424
- _this3.handlingEvent(result);
1352
+ _this4.handlingEvent(result);
1425
1353
 
1426
1354
  return result;
1427
1355
  });