UNPKG

qwc2-lts

Version:
19 lines 17.8 kB
function _typeof(o){"@babel/helpers - typeof";return _typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(o){return typeof o}:function(o){return o&&"function"==typeof Symbol&&o.constructor===Symbol&&o!==Symbol.prototype?"symbol":typeof o},_typeof(o)}function _classCallCheck(a,n){if(!(a instanceof n))throw new TypeError("Cannot call a class as a function")}function _defineProperties(e,r){for(var t=0;t<r.length;t++){var o=r[t];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(e,_toPropertyKey(o.key),o)}}function _createClass(e,r,t){return r&&_defineProperties(e.prototype,r),t&&_defineProperties(e,t),Object.defineProperty(e,"prototype",{writable:!1}),e}function _callSuper(t,o,e){return o=_getPrototypeOf(o),_possibleConstructorReturn(t,_isNativeReflectConstruct()?Reflect.construct(o,e||[],_getPrototypeOf(t).constructor):o.apply(t,e))}function _possibleConstructorReturn(t,e){if(e&&("object"==_typeof(e)||"function"==typeof e))return e;if(void 0!==e)throw new TypeError("Derived constructors may only return object or undefined");return _assertThisInitialized(t)}function _assertThisInitialized(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}function _isNativeReflectConstruct(){try{var t=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){}))}catch(t){}return(_isNativeReflectConstruct=function _isNativeReflectConstruct(){return!!t})()}function _getPrototypeOf(t){return _getPrototypeOf=Object.setPrototypeOf?Object.getPrototypeOf.bind():function(t){return t.__proto__||Object.getPrototypeOf(t)},_getPrototypeOf(t)}function _inherits(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function");t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,writable:!0,configurable:!0}}),Object.defineProperty(t,"prototype",{writable:!1}),e&&_setPrototypeOf(t,e)}function _setPrototypeOf(t,e){return _setPrototypeOf=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(t,e){return t.__proto__=e,t},_setPrototypeOf(t,e)}function _defineProperty(e,r,t){return(r=_toPropertyKey(r))in e?Object.defineProperty(e,r,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[r]=t,e}function _toPropertyKey(t){var i=_toPrimitive(t,"string");return"symbol"==_typeof(i)?i:i+""}function _toPrimitive(t,r){if("object"!=_typeof(t)||!t)return t;var e=t[Symbol.toPrimitive];if(void 0!==e){var i=e.call(t,r||"default");if("object"!=_typeof(i))return i;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===r?String:Number)(t)}/** * Copyright 2024 Sourcepole AG * All rights reserved. * * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. */import React from"react";import Coordinates from"@giro3d/giro3d/core/geographic/Coordinates";import classNames from"classnames";import PropTypes from"prop-types";import{Raycaster,Vector2,Vector3}from"three";import{MapControls}from"three/addons/controls/MapControls";import Icon from"../Icon";import"./style/MapControls3D.css";var MapControls3D=/*#__PURE__*/function(_React$Component){function MapControls3D(props){var _this;_classCallCheck(this,MapControls3D);_this=_callSuper(this,MapControls3D,[props]);_defineProperty(_this,"state",{firstPerson:false});_defineProperty(_this,"keyHandler",function(event){if(event.repeat){return}else if(event.key==="ArrowUp"){if(event.ctrlKey)_this.tilt(event,0,1,true);else _this.pan(event,0,1,true)}else if(event.key==="ArrowDown"){if(event.ctrlKey)_this.tilt(event,0,-1,true);else _this.pan(event,0,-1,true)}else if(event.key==="ArrowLeft"){if(event.ctrlKey)_this.tilt(event,1,0,true);else _this.pan(event,1,0,true)}else if(event.key==="ArrowRight"){if(event.ctrlKey)_this.tilt(event,-1,0,true);else _this.pan(event,-1,0,true)}});_defineProperty(_this,"home",function(){_this.leaveFirstPerson();var extent=_this.props.sceneContext.map.extent;var bounds=[extent.west,extent.south,extent.east,extent.north];_this.setViewToExtent(bounds)});_defineProperty(_this,"pan",function(ev,dx,dy){var keyboard=arguments.length>3&&arguments[3]!==undefined?arguments[3]:false;// Pan faster the heigher one is above the terrain var d=_this.state.firstPerson?200000:100+(_this.props.sceneContext.scene.view.camera.position.z-_this.props.sceneContext.scene.view.controls.target.z)/250;var delta=new Vector2(dx,dy).multiplyScalar(d);_this.animationInterrupted=false;var lastTimestamp=new Date/1000;var _animate=function animate(){if(_this.animationInterrupted){return}// Pan <delta> distance per second var timestamp=new Date/1000;var k=timestamp-lastTimestamp;lastTimestamp=timestamp;_this.props.sceneContext.scene.view.controls._pan(delta.x*k,delta.y*k);_this.props.sceneContext.scene.notifyChange();requestAnimationFrame(_animate)};requestAnimationFrame(_animate);var element=keyboard?ev.target:ev.view;var event=keyboard?"keyup":"mouseup";element.addEventListener(event,function(){_this.animationInterrupted=true},{once:true})});_defineProperty(_this,"tilt",function(ev,yaw,az){var keyboard=arguments.length>3&&arguments[3]!==undefined?arguments[3]:false;if(_this.state.firstPerson){az*=-1;yaw*=-1}// Pan faster the heigher one is above the terrain _this.animationInterrupted=false;var lastTimestamp=new Date/1000;var _animate2=function animate(){if(_this.animationInterrupted){return}// Pan <delta> distance per second var timestamp=new Date/1000;var k=timestamp-lastTimestamp;lastTimestamp=timestamp;if(az){_this.props.sceneContext.scene.view.controls._rotateUp(az*k)}if(yaw){_this.props.sceneContext.scene.view.controls._rotateLeft(yaw*k)}_this.props.sceneContext.scene.notifyChange();requestAnimationFrame(_animate2)};requestAnimationFrame(_animate2);var element=keyboard?ev.target:ev.view;var event=keyboard?"keyup":"mouseup";element.addEventListener(event,function(){_this.animationInterrupted=true},{once:true})});_defineProperty(_this,"resetTilt",function(){if(_this.state.firstPerson){var target=_this.props.sceneContext.scene.view.controls.target;var camerapos=_this.props.sceneContext.scene.view.camera.position;_this.props.sceneContext.scene.view.controls.target.set(target.x,target.y,camerapos.z)}else{// Animate from old to new position var _target=_this.props.sceneContext.scene.view.controls.target;var oldPosition=_this.props.sceneContext.scene.view.camera.position.clone();var oldYaw=_this.props.sceneContext.scene.view.controls.getAzimuthalAngle();var newPosition=new Vector3(_target.x,_target.y,_target.distanceTo(oldPosition));var startTime=new Date/1000;_this.animationInterrupted=false;var _animate3=function animate(){if(!_this.props.sceneContext.scene||_this.animationInterrupted){return}var duration=2;var elapsed=new Date/1000-startTime;var x=elapsed/duration;var k=0.5*(1-Math.cos(x*Math.PI));var currentPosition=new Vector3().lerpVectors(oldPosition,newPosition,k);currentPosition.x-=_target.x;currentPosition.y-=_target.y;currentPosition.applyAxisAngle(new Vector3(0,0,1),-oldYaw*k);currentPosition.x+=_target.x;currentPosition.y+=_target.y;_this.props.sceneContext.scene.view.camera.position.copy(currentPosition);_this.props.sceneContext.scene.notifyChange();if(elapsed<duration){requestAnimationFrame(_animate3)}else{_this.props.sceneContext.scene.view.camera.position.copy(newPosition);_this.props.sceneContext.scene.notifyChange()}};requestAnimationFrame(_animate3)}});_defineProperty(_this,"setViewToExtent",function(bounds){var _elevationResult$samp;var angle=arguments.length>1&&arguments[1]!==undefined?arguments[1]:0;if(_this.state.firstPerson){_this.leaveFirstPerson()}var center={x:0.5*(bounds[0]+bounds[2]),y:0.5*(bounds[1]+bounds[3])};var elevationResult=_this.props.sceneContext.map.getElevation({coordinates:new Coordinates(_this.props.sceneContext.mapCrs,center.x,center.y)});elevationResult.samples.sort(function(a,b){return a.resolution>b.resolution});center.z=((_elevationResult$samp=elevationResult.samples[0])===null||_elevationResult$samp===void 0?void 0:_elevationResult$samp.elevation)||0;// Camera height to width bbox width var fov=35/180*Math.PI;var cameraHeight=(bounds[2]-bounds[0])/(2*Math.tan(fov/2));// Animate from old to new position/target var oldPosition=_this.props.sceneContext.scene.view.camera.position.clone();var oldTarget=_this.props.sceneContext.scene.view.controls.target.clone();var oldYaw=_this.props.sceneContext.scene.view.controls.getAzimuthalAngle();var newPosition=new Vector3(center.x,center.y,center.z+cameraHeight);var newTarget=new Vector3(center.x,center.y,center.z);var rotateAngle=-oldYaw+angle;while(rotateAngle>Math.PI){rotateAngle-=2*Math.PI}while(rotateAngle<-Math.PI){rotateAngle+=2*Math.PI}var startTime=new Date/1000;_this.animationInterrupted=false;var _animate4=function animate(){if(!_this.props.sceneContext.scene||_this.animationInterrupted){return}var duration=2;var elapsed=new Date/1000-startTime;var x=elapsed/duration;var k=0.5*(1-Math.cos(x*Math.PI));var currentPosition=new Vector3().lerpVectors(oldPosition,newPosition,k);var currentTarget=new Vector3().lerpVectors(oldTarget,newTarget,k);currentPosition.x-=currentTarget.x;currentPosition.y-=currentTarget.y;currentPosition.applyAxisAngle(new Vector3(0,0,1),rotateAngle*k);currentPosition.x+=currentTarget.x;currentPosition.y+=currentTarget.y;_this.props.sceneContext.scene.view.camera.position.copy(currentPosition);_this.props.sceneContext.scene.view.controls.target.copy(currentTarget);_this.props.sceneContext.scene.notifyChange();if(elapsed<duration){requestAnimationFrame(_animate4)}else{_this.props.sceneContext.scene.view.camera.position.copy(newPosition);_this.props.sceneContext.scene.view.controls.target.copy(newTarget);_this.props.sceneContext.scene.view.controls._rotateLeft(-angle);_this.props.sceneContext.scene.notifyChange()}};requestAnimationFrame(_animate4)});_defineProperty(_this,"updateControlsTarget",function(){var _terrInter$point$z,_terrInter$point;var target=_this.props.sceneContext.scene.view.controls.target;if(_this.prevTarget&&_this.prevTarget.distanceToSquared(target)<50){return}_this.prevTarget=target.clone();var x=target.x;var y=target.y;var raycaster=new Raycaster;// Query highest resolution terrain tile (i.e. tile with no children) raycaster.set(new Vector3(x,y,target.z+100000),new Vector3(0,0,-1));var terrInter=raycaster.intersectObjects([_this.props.sceneContext.map.object3d]).filter(function(result){return result.object.children.length===0})[0];var terrainHeight=(_terrInter$point$z=terrInter===null||terrInter===void 0||(_terrInter$point=terrInter.point)===null||_terrInter$point===void 0?void 0:_terrInter$point.z)!==null&&_terrInter$point$z!==void 0?_terrInter$point$z:0;// FIXME: Why does raycaster.intersectObjects on terrain return 0-ish even when above terrain? if(terrainHeight<=1){return}if(_this.state.firstPerson){var delta=terrainHeight+_this.personHeight-_this.props.sceneContext.scene.view.camera.position.z;_this.props.sceneContext.scene.view.camera.position.z+=delta;_this.props.sceneContext.scene.view.controls.target.z+=delta;return}var cameraHeight=_this.props.sceneContext.scene.view.camera.position.z;// If camera height is at terrain height, target height should be at terrain height // If camera height is at twice the terrain height or further, target height should be zero var targetHeight=terrainHeight>0?terrainHeight*Math.max(0,1-(cameraHeight-terrainHeight)/terrainHeight):0;_this.props.sceneContext.scene.view.controls.target.z=targetHeight});_defineProperty(_this,"stopAnimations",function(){_this.animationInterrupted=true});_defineProperty(_this,"switchToFirstPersonView",function(ev){if(!_this.state.firstPerson){_this.setupFirstPerson(ev)}});_defineProperty(_this,"toggleFirstPersonControls",function(){if(_this.state.firstPerson){_this.leaveFirstPerson()}else{_this.props.sceneContext.scene.domElement.addEventListener("click",_this.setupFirstPerson,{once:true})}});_defineProperty(_this,"setupFirstPerson",function(ev){var rect=ev.target.getBoundingClientRect();var mouseX=(ev.clientX-rect.left)/rect.width*2-1;var mouseY=-((ev.clientY-rect.top)/rect.height)*2+1;var intersection=_this.props.sceneContext.getSceneIntersection(mouseX,mouseY,false);if(!intersection){return}var pos=intersection.point;_this.props.sceneContext.getTerrainHeight([pos.x,pos.y]).then(function(z){// Animate from old to new position/target var oldPosition=_this.props.sceneContext.scene.view.camera.position.clone();var oldTarget=_this.props.sceneContext.scene.view.controls.target.clone();var newPosition=new Vector3(pos.x,pos.y,z+_this.personHeight);var newTarget=new Vector3(pos.x,pos.y+300,z+_this.personHeight);var startTime=new Date/1000;_this.animationInterrupted=false;var _animate5=function animate(){if(!_this.props.sceneContext.scene||_this.animationInterrupted){return}var duration=2;var elapsed=new Date/1000-startTime;var x=elapsed/duration;var k=0.5*(1-Math.cos(x*Math.PI));var currentPosition=new Vector3().lerpVectors(oldPosition,newPosition,k);var currentTarget=new Vector3().lerpVectors(oldTarget,newTarget,k);_this.props.sceneContext.scene.view.camera.position.copy(currentPosition);_this.props.sceneContext.scene.view.controls.target.copy(currentTarget);_this.props.sceneContext.scene.notifyChange();if(elapsed<duration){requestAnimationFrame(_animate5)}else{_this.props.sceneContext.scene.view.camera.position.copy(newPosition);_this.props.sceneContext.scene.view.controls.target.set(pos.x,pos.y+0.1,z+_this.personHeight);_this.props.sceneContext.scene.notifyChange();_this.controls.maxPolarAngle=0.8*Math.PI;_this.controls.panSpeed=600;_this.controls.enableZoom=false;_this.setState({firstPerson:true})}};requestAnimationFrame(_animate5)})});_defineProperty(_this,"leaveFirstPerson",function(){_this.controls.maxPolarAngle=Math.PI*0.5;_this.controls.panSpeed=1;_this.controls.enableZoom=true;_this.setState({firstPerson:false},function(){var cameraPos=_this.props.sceneContext.scene.view.camera.position;var bounds=[cameraPos.x-1000,cameraPos.y-1000,cameraPos.x+1000,cameraPos.y+1000];_this.setViewToExtent(bounds)})});_this.animationInterrupted=false;_this.personHeight=2;_this.prevTarget=null;return _this}_inherits(MapControls3D,_React$Component);return _createClass(MapControls3D,[{key:"componentDidMount",value:function componentDidMount(){var sceneElement=this.props.sceneContext.scene.domElement;sceneElement.tabIndex=0;this.controls=new MapControls(this.props.sceneContext.scene.view.camera,sceneElement);this.controls.zoomToCursor=true;this.controls.enableDamping=true;this.controls.dampingFactor=0.2;this.controls.maxPolarAngle=Math.PI*0.5;sceneElement.addEventListener("keydown",this.keyHandler);this.props.sceneContext.scene.view.setControls(this.controls);var targetPos=this.props.sceneContext.scene.view.camera.position.clone();targetPos.z=0;this.controls.target=targetPos;this.controls.addEventListener("change",this.updateControlsTarget);sceneElement.addEventListener("dblclick",this.switchToFirstPersonView)}},{key:"componentWillUnmount",value:function componentWillUnmount(){this.animationInterrupted=true;var sceneElement=this.props.sceneContext.scene.domElement;sceneElement.addEventListener("keydown",this.keyHandler);this.controls.removeEventListener("change",this.updateControlsTarget);this.props.sceneContext.scene.view.setControls(null);this.controls.dispose();this.controls=null;this.props.sceneContext.scene.domElement.removeEventListener("dblclick",this.switchToFirstPersonView)}},{key:"render",value:function render(){var _this2=this;var firstPersonButtonClasses=classNames({"map3d-firstperson-button":true,"map3d-firstperson-button-active":this.state.firstPerson});return[/*#__PURE__*/React.createElement("div",{className:"map3d-nav-pan",key:"MapPanWidget"},/*#__PURE__*/React.createElement("span",null),/*#__PURE__*/React.createElement(Icon,{icon:"chevron-up",onMouseDown:function onMouseDown(ev){return _this2.pan(ev,0,1)}}),/*#__PURE__*/React.createElement("span",null),/*#__PURE__*/React.createElement(Icon,{icon:"chevron-left",onMouseDown:function onMouseDown(ev){return _this2.pan(ev,1,0)}}),/*#__PURE__*/React.createElement(Icon,{icon:"home",onClick:function onClick(){return _this2.home()}}),/*#__PURE__*/React.createElement(Icon,{icon:"chevron-right",onMouseDown:function onMouseDown(ev){return _this2.pan(ev,-1,0)}}),/*#__PURE__*/React.createElement("span",null),/*#__PURE__*/React.createElement(Icon,{icon:"chevron-down",onMouseDown:function onMouseDown(ev){return _this2.pan(ev,0,-1)}}),/*#__PURE__*/React.createElement("span",null)),/*#__PURE__*/React.createElement("div",{className:"map3d-nav-rotate",key:"MapRotateWidget"},/*#__PURE__*/React.createElement("span",null),/*#__PURE__*/React.createElement(Icon,{icon:"tilt-up",onMouseDown:function onMouseDown(ev){return _this2.tilt(ev,0,1)}}),/*#__PURE__*/React.createElement("span",null),/*#__PURE__*/React.createElement(Icon,{icon:"tilt-left",onMouseDown:function onMouseDown(ev){return _this2.tilt(ev,1,0)}}),/*#__PURE__*/React.createElement(Icon,{icon:"point",onClick:function onClick(){return _this2.resetTilt()}}),/*#__PURE__*/React.createElement(Icon,{icon:"tilt-right",onMouseDown:function onMouseDown(ev){return _this2.tilt(ev,-1,0)}}),/*#__PURE__*/React.createElement("span",null),/*#__PURE__*/React.createElement(Icon,{icon:"tilt-down",onMouseDown:function onMouseDown(ev){return _this2.tilt(ev,0,-1)}}),/*#__PURE__*/React.createElement("span",null)),/*#__PURE__*/React.createElement("div",{className:firstPersonButtonClasses,key:"FirstPersonButton",onClick:this.toggleFirstPersonControls},/*#__PURE__*/React.createElement(Icon,{icon:"person"}))]}}])}(React.Component);_defineProperty(MapControls3D,"propTypes",{sceneContext:PropTypes.object});export{MapControls3D as default};