UNPKG

cione-comp-lib

Version:

`$ yarn add cione-comp-lib` 或者 `$ npm i cione-comp-lib -S`

467 lines (466 loc) 15.5 kB
import Base from "../../../claygl/src/core/Base.mjs"; import Vector2 from "../../../claygl/src/math/Vector2.mjs"; import Vector3 from "../../../claygl/src/math/Vector3.mjs"; import retrieve from "./retrieve.mjs"; var firstNotNull = retrieve.firstNotNull; var MOUSE_BUTTON_KEY_MAP = { left: 0, middle: 1, right: 2 }; function convertToArray(val) { if (!(val instanceof Array)) { val = [val, val]; } return val; } var OrbitControl = Base.extend(function() { return { zr: null, viewGL: null, _center: new Vector3(), minDistance: 0.5, maxDistance: 1.5, maxOrthographicSize: 300, minOrthographicSize: 30, minAlpha: -90, maxAlpha: 90, minBeta: -Infinity, maxBeta: Infinity, autoRotateAfterStill: 0, autoRotateDirection: "cw", autoRotateSpeed: 60, damping: 0.8, rotateSensitivity: 1, zoomSensitivity: 1, panSensitivity: 1, panMouseButton: "middle", rotateMouseButton: "left", _mode: "rotate", _camera: null, _needsUpdate: false, _rotating: false, _phi: 0, _theta: 0, _mouseX: 0, _mouseY: 0, _rotateVelocity: new Vector2(), _panVelocity: new Vector2(), _distance: 500, _zoomSpeed: 0, _stillTimeout: 0, _animators: [] }; }, function() { ["_mouseDownHandler", "_mouseWheelHandler", "_mouseMoveHandler", "_mouseUpHandler", "_pinchHandler", "_contextMenuHandler", "_update"].forEach(function(hdlName) { this[hdlName] = this[hdlName].bind(this); }, this); }, { init: function() { var zr = this.zr; if (zr) { zr.on("mousedown", this._mouseDownHandler); zr.on("globalout", this._mouseUpHandler); zr.on("mousewheel", this._mouseWheelHandler); zr.on("pinch", this._pinchHandler); zr.animation.on("frame", this._update); zr.dom.addEventListener("contextmenu", this._contextMenuHandler); } }, dispose: function() { var zr = this.zr; if (zr) { zr.off("mousedown", this._mouseDownHandler); zr.off("mousemove", this._mouseMoveHandler); zr.off("mouseup", this._mouseUpHandler); zr.off("mousewheel", this._mouseWheelHandler); zr.off("pinch", this._pinchHandler); zr.off("globalout", this._mouseUpHandler); zr.dom.removeEventListener("contextmenu", this._contextMenuHandler); zr.animation.off("frame", this._update); } this.stopAllAnimation(); }, getDistance: function() { return this._distance; }, setDistance: function(distance) { this._distance = distance; this._needsUpdate = true; }, getOrthographicSize: function() { return this._orthoSize; }, setOrthographicSize: function(size) { this._orthoSize = size; this._needsUpdate = true; }, getAlpha: function() { return this._theta / Math.PI * 180; }, getBeta: function() { return -this._phi / Math.PI * 180; }, getCenter: function() { return this._center.toArray(); }, setAlpha: function(alpha) { alpha = Math.max(Math.min(this.maxAlpha, alpha), this.minAlpha); this._theta = alpha / 180 * Math.PI; this._needsUpdate = true; }, setBeta: function(beta) { beta = Math.max(Math.min(this.maxBeta, beta), this.minBeta); this._phi = -beta / 180 * Math.PI; this._needsUpdate = true; }, setCenter: function(centerArr) { this._center.setArray(centerArr); }, setViewGL: function(viewGL) { this.viewGL = viewGL; }, getCamera: function() { return this.viewGL.camera; }, setFromViewControlModel: function(viewControlModel, extraOpts) { extraOpts = extraOpts || {}; var baseDistance = extraOpts.baseDistance || 0; var baseOrthoSize = extraOpts.baseOrthoSize || 1; var projection = viewControlModel.get("projection"); if (projection !== "perspective" && projection !== "orthographic" && projection !== "isometric") { projection = "perspective"; } this._projection = projection; this.viewGL.setProjection(projection); var targetDistance = viewControlModel.get("distance") + baseDistance; var targetOrthographicSize = viewControlModel.get("orthographicSize") + baseOrthoSize; [["damping", 0.8], ["autoRotate", false], ["autoRotateAfterStill", 3], ["autoRotateDirection", "cw"], ["autoRotateSpeed", 10], ["minDistance", 30], ["maxDistance", 400], ["minOrthographicSize", 30], ["maxOrthographicSize", 300], ["minAlpha", -90], ["maxAlpha", 90], ["minBeta", -Infinity], ["maxBeta", Infinity], ["rotateSensitivity", 1], ["zoomSensitivity", 1], ["panSensitivity", 1], ["panMouseButton", "left"], ["rotateMouseButton", "middle"]].forEach(function(prop) { this[prop[0]] = firstNotNull(viewControlModel.get(prop[0]), prop[1]); }, this); this.minDistance += baseDistance; this.maxDistance += baseDistance; this.minOrthographicSize += baseOrthoSize, this.maxOrthographicSize += baseOrthoSize; var ecModel = viewControlModel.ecModel; var animationOpts = {}; ["animation", "animationDurationUpdate", "animationEasingUpdate"].forEach(function(key) { animationOpts[key] = firstNotNull(viewControlModel.get(key), ecModel && ecModel.get(key)); }); var alpha = firstNotNull(extraOpts.alpha, viewControlModel.get("alpha")) || 0; var beta = firstNotNull(extraOpts.beta, viewControlModel.get("beta")) || 0; var center = firstNotNull(extraOpts.center, viewControlModel.get("center")) || [0, 0, 0]; if (animationOpts.animation && animationOpts.animationDurationUpdate > 0 && this._notFirst) { this.animateTo({ alpha, beta, center, distance: targetDistance, orthographicSize: targetOrthographicSize, easing: animationOpts.animationEasingUpdate, duration: animationOpts.animationDurationUpdate }); } else { this.setDistance(targetDistance); this.setAlpha(alpha); this.setBeta(beta); this.setCenter(center); this.setOrthographicSize(targetOrthographicSize); } this._notFirst = true; this._validateProperties(); }, _validateProperties: function() { }, animateTo: function(opts) { var zr = this.zr; var self = this; var obj = {}; var target = {}; if (opts.distance != null) { obj.distance = this.getDistance(); target.distance = opts.distance; } if (opts.orthographicSize != null) { obj.orthographicSize = this.getOrthographicSize(); target.orthographicSize = opts.orthographicSize; } if (opts.alpha != null) { obj.alpha = this.getAlpha(); target.alpha = opts.alpha; } if (opts.beta != null) { obj.beta = this.getBeta(); target.beta = opts.beta; } if (opts.center != null) { obj.center = this.getCenter(); target.center = opts.center; } return this._addAnimator(zr.animation.animate(obj).when(opts.duration || 1e3, target).during(function() { if (obj.alpha != null) { self.setAlpha(obj.alpha); } if (obj.beta != null) { self.setBeta(obj.beta); } if (obj.distance != null) { self.setDistance(obj.distance); } if (obj.center != null) { self.setCenter(obj.center); } if (obj.orthographicSize != null) { self.setOrthographicSize(obj.orthographicSize); } self._needsUpdate = true; })).start(opts.easing || "linear"); }, stopAllAnimation: function() { for (var i = 0; i < this._animators.length; i++) { this._animators[i].stop(); } this._animators.length = 0; }, update: function() { this._needsUpdate = true; this._update(20); }, _isAnimating: function() { return this._animators.length > 0; }, _update: function(deltaTime) { if (this._rotating) { var radian = (this.autoRotateDirection === "cw" ? 1 : -1) * this.autoRotateSpeed / 180 * Math.PI; this._phi -= radian * deltaTime / 1e3; this._needsUpdate = true; } else if (this._rotateVelocity.len() > 0) { this._needsUpdate = true; } if (Math.abs(this._zoomSpeed) > 0.1 || this._panVelocity.len() > 0) { this._needsUpdate = true; } if (!this._needsUpdate) { return; } deltaTime = Math.min(deltaTime, 50); this._updateDistanceOrSize(deltaTime); this._updatePan(deltaTime); this._updateRotate(deltaTime); this._updateTransform(); this.getCamera().update(); this.zr && this.zr.refresh(); this.trigger("update"); this._needsUpdate = false; }, _updateRotate: function(deltaTime) { var velocity = this._rotateVelocity; this._phi = velocity.y * deltaTime / 20 + this._phi; this._theta = velocity.x * deltaTime / 20 + this._theta; this.setAlpha(this.getAlpha()); this.setBeta(this.getBeta()); this._vectorDamping(velocity, Math.pow(this.damping, deltaTime / 16)); }, _updateDistanceOrSize: function(deltaTime) { if (this._projection === "perspective") { this._setDistance(this._distance + this._zoomSpeed * deltaTime / 20); } else { this._setOrthoSize(this._orthoSize + this._zoomSpeed * deltaTime / 20); } this._zoomSpeed *= Math.pow(this.damping, deltaTime / 16); }, _setDistance: function(distance) { this._distance = Math.max(Math.min(distance, this.maxDistance), this.minDistance); }, _setOrthoSize: function(size) { this._orthoSize = Math.max(Math.min(size, this.maxOrthographicSize), this.minOrthographicSize); var camera = this.getCamera(); var cameraHeight = this._orthoSize; var cameraWidth = cameraHeight / this.viewGL.viewport.height * this.viewGL.viewport.width; camera.left = -cameraWidth / 2; camera.right = cameraWidth / 2; camera.top = cameraHeight / 2; camera.bottom = -cameraHeight / 2; }, _updatePan: function(deltaTime) { var velocity = this._panVelocity; var len = this._distance; var target = this.getCamera(); var yAxis = target.worldTransform.y; var xAxis = target.worldTransform.x; this._center.scaleAndAdd(xAxis, -velocity.x * len / 200).scaleAndAdd(yAxis, -velocity.y * len / 200); this._vectorDamping(velocity, 0); }, _updateTransform: function() { var camera = this.getCamera(); var dir = new Vector3(); var theta = this._theta + Math.PI / 2; var phi = this._phi + Math.PI / 2; var r = Math.sin(theta); dir.x = r * Math.cos(phi); dir.y = -Math.cos(theta); dir.z = r * Math.sin(phi); camera.position.copy(this._center).scaleAndAdd(dir, this._distance); camera.rotation.identity().rotateY(-this._phi).rotateX(-this._theta); }, _startCountingStill: function() { clearTimeout(this._stillTimeout); var time = this.autoRotateAfterStill; var self = this; if (!isNaN(time) && time > 0) { this._stillTimeout = setTimeout(function() { self._rotating = true; }, time * 1e3); } }, _vectorDamping: function(v, damping) { var speed = v.len(); speed = speed * damping; if (speed < 1e-4) { speed = 0; } v.normalize().scale(speed); }, _decomposeTransform: function() { if (!this.getCamera()) { return; } this.getCamera().updateWorldTransform(); var forward = this.getCamera().worldTransform.z; var alpha = Math.asin(forward.y); var beta = Math.atan2(forward.x, forward.z); this._theta = alpha; this._phi = -beta; this.setBeta(this.getBeta()); this.setAlpha(this.getAlpha()); if (this.getCamera().aspect) { this._setDistance(this.getCamera().position.dist(this._center)); } else { this._setOrthoSize(this.getCamera().top - this.getCamera().bottom); } }, _mouseDownHandler: function(e) { if (e.target) { return; } if (this._isAnimating()) { return; } var x = e.offsetX; var y = e.offsetY; if (this.viewGL && !this.viewGL.containPoint(x, y)) { return; } this.zr.on("mousemove", this._mouseMoveHandler); this.zr.on("mouseup", this._mouseUpHandler); if (e.event.targetTouches) { if (e.event.targetTouches.length === 1) { this._mode = "rotate"; } } else { if (e.event.button === MOUSE_BUTTON_KEY_MAP[this.rotateMouseButton]) { this._mode = "rotate"; } else if (e.event.button === MOUSE_BUTTON_KEY_MAP[this.panMouseButton]) { this._mode = "pan"; } else { this._mode = ""; } } this._rotateVelocity.set(0, 0); this._rotating = false; if (this.autoRotate) { this._startCountingStill(); } this._mouseX = e.offsetX; this._mouseY = e.offsetY; }, _mouseMoveHandler: function(e) { if (e.target && e.target.__isGLToZRProxy) { return; } if (this._isAnimating()) { return; } var panSensitivity = convertToArray(this.panSensitivity); var rotateSensitivity = convertToArray(this.rotateSensitivity); if (this._mode === "rotate") { this._rotateVelocity.y = (e.offsetX - this._mouseX) / this.zr.getHeight() * 2 * rotateSensitivity[0]; this._rotateVelocity.x = (e.offsetY - this._mouseY) / this.zr.getWidth() * 2 * rotateSensitivity[1]; } else if (this._mode === "pan") { this._panVelocity.x = (e.offsetX - this._mouseX) / this.zr.getWidth() * panSensitivity[0] * 400; this._panVelocity.y = (-e.offsetY + this._mouseY) / this.zr.getHeight() * panSensitivity[1] * 400; } this._mouseX = e.offsetX; this._mouseY = e.offsetY; e.event.preventDefault(); }, _mouseWheelHandler: function(e) { if (this._isAnimating()) { return; } var delta = e.event.wheelDelta || -e.event.detail; this._zoomHandler(e, delta); }, _pinchHandler: function(e) { if (this._isAnimating()) { return; } this._zoomHandler(e, e.pinchScale > 1 ? 1 : -1); this._mode = ""; }, _zoomHandler: function(e, delta) { if (delta === 0) { return; } var x = e.offsetX; var y = e.offsetY; if (this.viewGL && !this.viewGL.containPoint(x, y)) { return; } var speed; if (this._projection === "perspective") { speed = Math.max(Math.max(Math.min(this._distance - this.minDistance, this.maxDistance - this._distance)) / 20, 0.5); } else { speed = Math.max(Math.max(Math.min(this._orthoSize - this.minOrthographicSize, this.maxOrthographicSize - this._orthoSize)) / 20, 0.5); } this._zoomSpeed = (delta > 0 ? -1 : 1) * speed * this.zoomSensitivity; this._rotating = false; if (this.autoRotate && this._mode === "rotate") { this._startCountingStill(); } e.event.preventDefault(); }, _mouseUpHandler: function() { this.zr.off("mousemove", this._mouseMoveHandler); this.zr.off("mouseup", this._mouseUpHandler); }, _isRightMouseButtonUsed: function() { return this.rotateMouseButton === "right" || this.panMouseButton === "right"; }, _contextMenuHandler: function(e) { if (this._isRightMouseButtonUsed()) { e.preventDefault(); } }, _addAnimator: function(animator) { var animators = this._animators; animators.push(animator); animator.done(function() { var idx = animators.indexOf(animator); if (idx >= 0) { animators.splice(idx, 1); } }); return animator; } }); Object.defineProperty(OrbitControl.prototype, "autoRotate", { get: function(val) { return this._autoRotate; }, set: function(val) { this._autoRotate = val; this._rotating = val; } }); var OrbitControl$1 = OrbitControl; export { OrbitControl$1 as default };