123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388 |
- import * as THREE from "../../libs/three.js/build/three.module.js";
- import {transitions, easing, lerp} from '../utils/transitions.js'
- import math from '../utils/math.js'
- import Common from '../utils/Common'
- let sid = 0
-
- export class View extends THREE.EventDispatcher{
- constructor () {
- super()
- this.position = new THREE.Vector3(0, 0, 0);
- this.yaw = 0//Math.PI / 4; // = 4dkk lon + 90
- this._pitch = 0//-Math.PI / 4; //上下旋转 = 4dkk lat
- this.radius = 1;
- this.maxPitch = Math.PI / 2;
- this.minPitch = -Math.PI / 2;
-
- this.sid = sid++
- this.LookTransition = 'LookTransition'+this.sid
-
- }
- //add------
- applyToCamera(camera){
- camera.position.copy(this.position);
- camera.rotation.copy(this.rotation)
-
-
- camera.updateMatrix();
- camera.updateMatrixWorld();
- camera.matrixWorldInverse.copy(camera.matrixWorld).invert();
-
-
- }
-
- get rotation(){
- var rotation = new THREE.Euler;
- rotation.order = "ZXY";
- rotation.x = Math.PI / 2 + this.pitch;
- rotation.z = this.yaw;
- return rotation
- }
-
- set rotation(rotation){
- //因为 rotation的y不一定是0 , 所以不能直接逆着写。
- this.direction = new THREE.Vector3(0,0,-1).applyEuler(rotation)
- }
-
-
-
-
- copy(a){
- Common.CopyClassObject(this, a)
- }
-
- clone () {
- /* let c = new View();
- c.yaw = this.yaw;
- c._pitch = this.pitch;
- c.radius = this.radius;
- c.maxPitch = this.maxPitch;
- c.minPitch = this.minPitch;
- return c; */
-
- return Common.CloneClassObject(this)
- }
-
- //----------
-
-
-
- get pitch () {
- return this._pitch;
- }
- set pitch (angle) {
- this._pitch = Math.max(Math.min(angle, this.maxPitch), this.minPitch);
- }
- get direction () {
- let dir = new THREE.Vector3(0, 1, 0);
- dir.applyAxisAngle(new THREE.Vector3(1, 0, 0), this.pitch);
- dir.applyAxisAngle(new THREE.Vector3(0, 0, 1), this.yaw);
- return dir;
- }
- set direction (dir) {
- //if(dir.x === dir.y){
- if(dir.x === 0 && dir.y === 0){
- this.pitch = Math.PI / 2 * Math.sign(dir.z);
- }else{
- let yaw = Math.atan2(dir.y, dir.x) - Math.PI / 2;
- let pitch = Math.atan2(dir.z, Math.sqrt(dir.x * dir.x + dir.y * dir.y));
- this.yaw = yaw;
- this.pitch = pitch;
- }
-
- }
- lookAt(t){
- let V;
- if(arguments.length === 1){
- V = new THREE.Vector3().subVectors(t, this.position);
- }else if(arguments.length === 3){
- V = new THREE.Vector3().subVectors(new THREE.Vector3(...arguments), this.position);
- }
- let radius = V.length();
- let dir = V.normalize();
- this.radius = radius;
- this.direction = dir;
- }
- getPivot () {
- return new THREE.Vector3().addVectors(this.position, this.direction.multiplyScalar(this.radius));
- }
- getSide () {
- let side = new THREE.Vector3(1, 0, 0);
- side.applyAxisAngle(new THREE.Vector3(0, 0, 1), this.yaw);
- return side;
- }
- /* pan (x, y) {
- let dir = new THREE.Vector3(0, 1, 0);
- dir.applyAxisAngle(new THREE.Vector3(1, 0, 0), this.pitch);
- dir.applyAxisAngle(new THREE.Vector3(0, 0, 1), this.yaw);
- // let side = new THREE.Vector3(1, 0, 0);
- // side.applyAxisAngle(new THREE.Vector3(0, 0, 1), this.yaw);
- let side = this.getSide();
- let up = side.clone().cross(dir);
- let pan = side.multiplyScalar(x).add(up.multiplyScalar(y));
- this.position = this.position.add(pan);
- // this.target = this.target.add(pan);
- } */
- pan (x, y) { //发现pan其实就是translate
- this.translate(x, 0, y)
- }
- translate (x, y, z) {
- let dir = new THREE.Vector3(0, 1, 0);
- dir.applyAxisAngle(new THREE.Vector3(1, 0, 0), this.pitch);
- dir.applyAxisAngle(new THREE.Vector3(0, 0, 1), this.yaw);
- let side = new THREE.Vector3(1, 0, 0);
- side.applyAxisAngle(new THREE.Vector3(0, 0, 1), this.yaw);
- let up = side.clone().cross(dir);
- let t = side.multiplyScalar(x)
- .add(dir.multiplyScalar(y))
- .add(up.multiplyScalar(z));
- this.position = this.position.add(t);
- this.restrictPos()
- }
- translateWorld (x, y, z) {
- this.position.x += x;
- this.position.y += y;
- this.position.z += z;
- this.restrictPos()
- }
- restrictPos(){//add
- if(this.limitBound){
- this.position.clamp(this.limitBound.min, this.limitBound.max)
- }
- }
- setCubeView(dir) {
-
- switch(dir) {
- case "front":
- this.yaw = 0;
- this.pitch = 0;
- break;
- case "back":
- this.yaw = Math.PI;
- this.pitch = 0;
- break;
- case "left":
- this.yaw = -Math.PI / 2;
- this.pitch = 0;
- break;
- case "right":
- this.yaw = Math.PI / 2;
- this.pitch = 0;
- break;
- case "top":
- this.yaw = 0;
- this.pitch = -Math.PI / 2;
- break;
- case "bottom":
- this.yaw = -Math.PI;
- this.pitch = Math.PI / 2;
- break;
- }
- }
-
-
-
- isFlying(){
- return transitions.getById(this.LookTransition).length > 0
- }
-
- cancelFlying(){//外界只能通过这个来cancel
- transitions.cancelById(this.LookTransition, true );
- }
-
- setView( info = {}){
- // position, target, duration = 0, callback = null, onUpdate = null, Easing='', cancelFun
- this.cancelFlying()
-
- let done = ()=>{
- if(endTarget){
- this.lookAt(endTarget); //compute radius for orbitcontrol
- }else if(endQuaternion){
- this.rotation = new THREE.Euler().setFromQuaternion(endQuaternion)
- }
-
- let f = ()=>{
- info.callback && info.callback()
- this.dispatchEvent('flyingDone')
- }
- if(info.duration){
- setTimeout(f,1)//延迟是为了使isFlying先为false
- }else{
- f() //有的需要迅速执行回调
- }
-
-
- }
-
- let endPosition = new THREE.Vector3().copy(info.position)
-
- const startPosition = this.position.clone();
- const startTarget = this.getPivot();
- let startQuaternion = math.getQuaFromPosAim(startPosition,startTarget)
-
- let endTarget = null, endQuaternion ;
-
-
-
-
- if(info.target ){
- endTarget = new THREE.Vector3().copy(info.target)
- endQuaternion = math.getQuaFromPosAim(endPosition,endTarget)
- }else if(info.quaternion){
- endQuaternion = info.quaternion.clone()
- }
-
-
- if(!info.duration){
- this.position.copy(endPosition);
- this.restrictPos()
-
- info.onUpdate && info.onUpdate(1)
- done()
-
- }else{
- transitions.start(lerp.vector(this.position, endPosition, (pos, progress)=>{
- let t = progress
-
- if(endQuaternion){
- let quaternion = (new THREE.Quaternion()).copy(startQuaternion)
- lerp.quaternion(quaternion, endQuaternion)(progress),
- this.rotation = new THREE.Euler().setFromQuaternion(quaternion)
- }
- this.restrictPos()
-
- info.onUpdate && info.onUpdate(t)//add
- }), info.duration, done, 0, info.Easing ? easing[info.Easing] : easing.easeInOutSine /*easeInOutQuad */,null, this.LookTransition, info.cancelFun);
- }
- }
-
-
- //平移Ortho相机
- moveOrthoCamera(viewport, info, duration, easeName){//boundSize优先于endZoom。
- let camera = viewport.camera
-
- let startZoom = camera.zoom
- let endPosition = info.endPosition
- let boundSize = info.boundSize
- let endZoom = info.endZoom
- let margin = info.margin || {x:0,y:0}/* 200 */ //像素
-
- if(info.bound){//需要修改boundSize以适应相机的旋转,当相机不在xy水平面上朝向z时
- endPosition = endPosition || info.bound.getCenter(new THREE.Vector3())
-
- let matrixRot = new THREE.Matrix4().makeRotationFromEuler(this.rotation)
- matrixRot.getInverse(matrixRot)
- let boundingBox = info.bound.clone().applyMatrix4(matrixRot)
- boundSize = boundingBox.getSize(new THREE.Vector3())
-
- }
-
- this.setView({ position:endPosition, duration,
- callback:()=>{//done
-
- },
- onUpdate:(progress)=>{
- if(boundSize || endZoom){
- if(boundSize){
- let aspect = boundSize.x / boundSize.y
- let w, h;
-
- if(camera.aspect > aspect){//视野更宽则用bound的纵向来决定
- h = boundSize.y
- endZoom = (viewport.resolution.y - margin.x) / h //注意,要在resolution不为0时执行
- }else{
- w = boundSize.x;
- endZoom = (viewport.resolution.x - margin.y) / w
- }
- //onUpdate时更新endzoom是因为画布大小可能更改
- }
-
- camera.zoom = endZoom * progress + startZoom * (1 - progress)
- camera.updateProjectionMatrix()
- }
- },
-
- Easing:easeName
-
- })
-
-
- }
-
-
-
- zoomOrthoCamera(camera, endZoom, pointer, duration, onProgress){//定点缩放
-
- let startZoom = camera.zoom
-
- let pointerPos = new THREE.Vector3(pointer.x, pointer.y,0.5);
-
-
- transitions.start(( progress)=>{
- let oldPos = pointerPos.clone().unproject(camera);
-
- camera.zoom = endZoom * progress + startZoom * (1 - progress)
- camera.updateProjectionMatrix()
-
-
- let newPos = pointerPos.clone().unproject(camera);
-
- //定点缩放, 恢复一下鼠标所在位置的位置改变量
- let moveVec = new THREE.Vector3().subVectors(newPos, oldPos)
-
- camera.position.sub(moveVec)
- this.position.copy(camera.position)
-
- onProgress && onProgress()
-
- } , duration, null/* done */, 0, easing.easeInOutSine, null, "zoomInView"/* , info.cancelFun */);
-
-
-
-
- }
-
-
-
- };
|