cione-comp-lib
Version:
`$ yarn add cione-comp-lib` 或者 `$ npm i cione-comp-lib -S`
467 lines (466 loc) • 15.5 kB
JavaScript
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 };