Diff
checker
文本
文本
图像
文档
Excel
文件夹
Legal
Enterprise
桌面版
定价
登录
下载 Diffchecker 桌面版
比较文本
查找两个文本文件之间的差异
工具
历史
实时编辑器
折叠未更改行
关闭换行
视图
拆分
统一
比对精度
智能
单词
字符
语法高亮
选择语法
忽略
文本转换
转到第一个差异
编辑输入
Diffchecker Desktop
运行Diffchecker最安全的方式。获取Diffchecker桌面应用:您的差异永远不会离开您的电脑!
获取桌面版
Untitled diff
创建于
11年前
差异永不过期
清除
导出
分享
解释
139 删除
行
总计
删除
字符
总计
删除
要继续使用此功能,请升级到
Diff
checker
Pro
查看价格
404 行
全部复制
411 添加
行
总计
添加
字符
总计
添加
要继续使用此功能,请升级到
Diff
checker
Pro
查看价格
648 行
全部复制
/**
/**
* @author qiao / https://github.com/qiao
* @author qiao / https://github.com/qiao
* @author mrdoob / http://mrdoob.com
* @author mrdoob / http://mrdoob.com
* @author alteredq / http://alteredqualia.com/
* @author alteredq / http://alteredqualia.com/
* @author WestLangley / http://github.com/WestLangley
* @author WestLangley / http://github.com/WestLangley
复制
已复制
复制
已复制
* @author erich666 / http://erichaines.com
*/
*/
复制
已复制
复制
已复制
/*global THREE, console */
// This set of controls performs orbiting, dollying (zooming), and panning. It maintains
// the "up" direction as +Y, unlike the TrackballControls. Touch on tablet and phones is
// supported.
//
// Orbit - left mouse / touch: one finger move
// Zoom - middle mouse, or mousewheel / touch: two finger spread or squish
// Pan - right mouse, or arrow keys / touch: three finter swipe
//
// This is a drop-in replacement for (most) TrackballControls used in examples.
// That is, include this js file and wherever you see:
// controls = new THREE.TrackballControls( camera );
// controls.target.z = 150;
// Simple substitute "OrbitControls" and the control should work as-is.
THREE.OrbitControls = function ( object, domElement ) {
THREE.OrbitControls = function ( object, domElement ) {
this.object = object;
this.object = object;
this.domElement = ( domElement !== undefined ) ? domElement : document;
this.domElement = ( domElement !== undefined ) ? domElement : document;
// API
// API
复制
已复制
复制
已复制
// Set to false to disable this control
this.enabled = true;
this.enabled = true;
复制
已复制
复制
已复制
this.
center
= new THREE.Vector3();
// "target" sets the location of focus, where the control orbits around
// and where it pans with respect to.
this.
target
= new THREE.Vector3();
复制
已复制
复制
已复制
this.userZoom = true;
// center is old, deprecated; use "target" instead
this.
userZoomSpeed
=
1.0
;
this.
center
=
this.target
;
复制
已复制
复制
已复制
this.
userRotate
=
true
;
// This option actually enables dollying in and out; left as "zoom" for
this.
userRotateSpeed
= 1.0;
// backwards compatibility
this.
noZoom
=
false
;
this.
zoomSpeed
= 1.0;
复制
已复制
复制
已复制
this.userPan = true
;
// Limits to how far you can dolly in and out
this.
user
PanSpeed =
2
.0;
this.minDistance = 0;
this.maxDistance = Infinity;
// Set to true to disable this control
this.noRotate = false;
this.rotateSpeed = 1.0;
// Set to true to disable this control
this.noPan = false
;
this.
key
PanSpeed =
7
.0;
// pixels moved per arrow key push
复制
已复制
复制
已复制
// Set to true to automatically rotate around the target
this.autoRotate = false;
this.autoRotate = false;
this.autoRotateSpeed = 2.0; // 30 seconds per round when fps is 60
this.autoRotateSpeed = 2.0; // 30 seconds per round when fps is 60
复制
已复制
复制
已复制
// How far you can orbit vertically, upper and lower limits.
// Range is 0 to Math.PI radians.
this.minPolarAngle = 0; // radians
this.minPolarAngle = 0; // radians
this.maxPolarAngle = Math.PI; // radians
this.maxPolarAngle = Math.PI; // radians
复制
已复制
复制
已复制
this.minDistance = 0;
// Set to true to disable use of the keys
this.
maxDistance
=
Infinity
;
this.
noKeys
=
false
;
复制
已复制
复制
已复制
//
65 /*A*/, 83 /*S*/, 68 /*D*/
//
The four arrow keys
this.keys = { LEFT: 37, UP: 38, RIGHT: 39, BOTTOM: 40
, ROTATE: 65, ZOOM: 83, PAN: 68
};
this.keys = { LEFT: 37, UP: 38, RIGHT: 39, BOTTOM: 40
};
复制
已复制
复制
已复制
////////////
// internals
// internals
var scope = this;
var scope = this;
var EPS = 0.000001;
var EPS = 0.000001;
复制
已复制
复制
已复制
var PIXELS_PER_ROUND = 1800;
var rotateStart = new THREE.Vector2();
var rotateStart = new THREE.Vector2();
var rotateEnd = new THREE.Vector2();
var rotateEnd = new THREE.Vector2();
var rotateDelta = new THREE.Vector2();
var rotateDelta = new THREE.Vector2();
复制
已复制
复制
已复制
var zoomStart
= new THREE.Vector2();
var panStart = new THREE.Vector2();
var
zoomEnd
= new THREE.Vector2();
var panEnd = new THREE.Vector2();
var
zoomDelta
= new THREE.Vector2();
var panDelta = new THREE.Vector2();
var panOffset = new THREE.Vector3();
var offset = new THREE.Vector3();
var dollyStart
= new THREE.Vector2();
var
dollyEnd
= new THREE.Vector2();
var
dollyDelta
= new THREE.Vector2();
var phiDelta = 0;
var phiDelta = 0;
var thetaDelta = 0;
var thetaDelta = 0;
var scale = 1;
var scale = 1;
复制
已复制
复制
已复制
var pan = new THREE.Vector3();
var lastPosition = new THREE.Vector3();
var lastPosition = new THREE.Vector3();
复制
已复制
复制
已复制
var lastQuaternion = new THREE.Quaternion();
复制
已复制
复制
已复制
var STATE = { NONE
: -1, ROTATE
: 0,
ZOOM
: 1, PAN
: 2
};
var STATE = { NONE
: -1, ROTATE
: 0,
DOLLY
: 1, PAN
: 2
, TOUCH_ROTATE : 3, TOUCH_DOLLY : 4, TOUCH_PAN : 5
};
var state = STATE.NONE;
var state = STATE.NONE;
复制
已复制
复制
已复制
// for reset
this.target0 = this.target.clone();
this.position0 = this.object.position.clone();
// so camera.up is the orbit axis
var quat = new THREE.Quaternion().setFromUnitVectors( object.up, new THREE.Vector3( 0, 1, 0 ) );
var quatInverse = quat.clone().inverse();
// events
// events
var changeEvent = { type: 'change' };
var changeEvent = { type: 'change' };
复制
已复制
复制
已复制
var startEvent = { type: 'start'};
var endEvent = { type: 'end'};
this.rotateLeft = function ( angle ) {
this.rotateLeft = function ( angle ) {
if ( angle === undefined ) {
if ( angle === undefined ) {
angle = getAutoRotationAngle();
angle = getAutoRotationAngle();
}
}
thetaDelta -= angle;
thetaDelta -= angle;
};
};
复制
已复制
复制
已复制
this.rotateRight = function ( angle ) {
if ( angle === undefined ) {
Text moved with changes to lines 224-228 (90.3% similarity)
angle = getAutoRotationAngle();
}
thetaDelta += angle;
};
this.rotateUp = function ( angle ) {
this.rotateUp = function ( angle ) {
if ( angle === undefined ) {
if ( angle === undefined ) {
angle = getAutoRotationAngle();
angle = getAutoRotationAngle();
}
}
phiDelta -= angle;
phiDelta -= angle;
};
};
复制
已复制
复制
已复制
this.
rotateDown
= function (
angle
) {
// pass in distance in world space to move left
this.
panLeft
= function (
distance
) {
复制
已复制
复制
已复制
if ( angle === undefined ) {
var te = this.object.matrix.elements;
复制
已复制
复制
已复制
angle = getAutoRotationAngle();
// get X column of matrix
panOffset.set( te[ 0 ], te[ 1 ], te[ 2 ] );
panOffset.multiplyScalar( - distance );
pan.add( panOffset );
复制
已复制
复制
已复制
}
};
复制
已复制
复制
已复制
phiDelta += angle;
// pass in distance in world space to move up
this.panUp = function ( distance ) {
var te = this.object.matrix.elements;
// get Y column of matrix
panOffset.set( te[ 4 ], te[ 5 ], te[ 6 ] );
panOffset.multiplyScalar( distance );
pan.add( panOffset );
};
};
复制
已复制
复制
已复制
// pass in x,y of change desired in pixel space,
// right and down are positive
this.pan = function ( deltaX, deltaY ) {
复制
已复制
复制
已复制
this.zoomIn = function ( zoomScale ) {
var element = scope.domElement === document ? scope.domElement.body : scope.domElement;
复制
已复制
复制
已复制
if (
zoomScale =
== undefined ) {
if (
scope.object.fov !
== undefined ) {
复制
已复制
复制
已复制
zoomScale = getZoomScale();
// perspective
var position = scope.object.position;
var offset = position.clone().sub( scope.target );
var targetDistance = offset.length();
// half of the fov is center to top of screen
targetDistance *= Math.tan( ( scope.object.fov / 2 ) * Math.PI / 180.0 );
// we actually don't use screenWidth, since perspective camera is fixed to screen height
scope.panLeft( 2 * deltaX * targetDistance / element.clientHeight );
scope.panUp( 2 * deltaY * targetDistance / element.clientHeight );
} else if ( scope.object.top !== undefined ) {
// orthographic
scope.panLeft( deltaX * (scope.object.right - scope.object.left) / element.clientWidth );
scope.panUp( deltaY * (scope.object.top - scope.object.bottom) / element.clientHeight );
} else {
// camera neither orthographic or perspective
console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - pan disabled.' );
}
}
复制
已复制
复制
已复制
scale /= zoomScale;
};
};
复制
已复制
复制
已复制
this.
zoomOut
= function (
zoomScale
) {
this.
dollyIn
= function (
dollyScale
) {
复制
已复制
复制
已复制
if (
zoomScale
=== undefined ) {
if (
dollyScale
=== undefined ) {
复制
已复制
复制
已复制
zoomScale
= getZoomScale();
dollyScale
= getZoomScale();
}
}
复制
已复制
复制
已复制
scale
*= zoomScale
;
scale
/= dollyScale
;
};
};
复制
已复制
复制
已复制
this.
pan
= function (
distance
) {
this.
dollyOut
= function (
dollyScale
) {
复制
已复制
复制
已复制
distance.transformDirection( this.object.matrix );
if ( dollyScale === undefined ) {
distance.multiplyScalar( scope.userPanSpeed );
复制
已复制
复制
已复制
Text moved with changes from lines 85-89 (90.3% similarity)
this.object.position.add( distance
);
dollyScale = getZoomScale(
);
this.center.add( distance )
;
}
scale *= dollyScale
;
};
};
this.update = function () {
this.update = function () {
var position = this.object.position;
var position = this.object.position;
复制
已复制
复制
已复制
var
offset
=
position
.clone(
).sub( this.
center
);
offset
.copy(
position
).sub( this.
target );
// rotate offset to "y-axis-is-up" space
offset.applyQuaternion( quat
);
// angle from z-axis around y-axis
// angle from z-axis around y-axis
var theta = Math.atan2( offset.x, offset.z );
var theta = Math.atan2( offset.x, offset.z );
// angle from y-axis
// angle from y-axis
var phi = Math.atan2( Math.sqrt( offset.x * offset.x + offset.z * offset.z ), offset.y );
var phi = Math.atan2( Math.sqrt( offset.x * offset.x + offset.z * offset.z ), offset.y );
if ( this.autoRotate ) {
if ( this.autoRotate ) {
this.rotateLeft( getAutoRotationAngle() );
this.rotateLeft( getAutoRotationAngle() );
}
}
theta += thetaDelta;
theta += thetaDelta;
phi += phiDelta;
phi += phiDelta;
// restrict phi to be between desired limits
// restrict phi to be between desired limits
phi = Math.max( this.minPolarAngle, Math.min( this.maxPolarAngle, phi ) );
phi = Math.max( this.minPolarAngle, Math.min( this.maxPolarAngle, phi ) );
// restrict phi to be betwee EPS and PI-EPS
// restrict phi to be betwee EPS and PI-EPS
phi = Math.max( EPS, Math.min( Math.PI - EPS, phi ) );
phi = Math.max( EPS, Math.min( Math.PI - EPS, phi ) );
var radius = offset.length() * scale;
var radius = offset.length() * scale;
// restrict radius to be between desired limits
// restrict radius to be between desired limits
radius = Math.max( this.minDistance, Math.min( this.maxDistance, radius ) );
radius = Math.max( this.minDistance, Math.min( this.maxDistance, radius ) );
复制
已复制
复制
已复制
// move target to panned location
this.target.add( pan );
offset.x = radius * Math.sin( phi ) * Math.sin( theta );
offset.x = radius * Math.sin( phi ) * Math.sin( theta );
offset.y = radius * Math.cos( phi );
offset.y = radius * Math.cos( phi );
offset.z = radius * Math.sin( phi ) * Math.cos( theta );
offset.z = radius * Math.sin( phi ) * Math.cos( theta );
复制
已复制
复制
已复制
position.copy( this.center ).add(
offset
);
// rotate
offset
back to "camera-up-vector-is-up" space
offset.applyQuaternion( quatInverse
);
复制
已复制
复制
已复制
this.object.lookAt( this.
center
);
position.copy( this.target ).add( offset );
this.object.lookAt( this.
target
);
thetaDelta = 0;
thetaDelta = 0;
phiDelta = 0;
phiDelta = 0;
scale = 1;
scale = 1;
复制
已复制
复制
已复制
pan.set( 0, 0, 0 );
复制
已复制
复制
已复制
if ( lastPosition.distanceTo
( this.object.position ) >
0
) {
// update condition is:
// min(camera displacement, camera rotation in radians)^2 > EPS
// using small-angle approximation cos(x/2) = 1 - x^2 / 8
if ( lastPosition.distanceTo
Squared
( this.object.position ) >
EPS
|| 8 * (1 - lastQuaternion.dot(this.object.quaternion)) > EPS
) {
this.dispatchEvent( changeEvent );
this.dispatchEvent( changeEvent );
lastPosition.copy( this.object.position );
lastPosition.copy( this.object.position );
复制
已复制
复制
已复制
lastQuaternion.copy (this.object.quaternion );
}
}
};
};
复制
已复制
复制
已复制
this.reset = function () {
state = STATE.NONE;
this.target.copy( this.target0 );
this.object.position.copy( this.position0 );
this.update();
};
function getAutoRotationAngle() {
function getAutoRotationAngle() {
return 2 * Math.PI / 60 / 60 * scope.autoRotateSpeed;
return 2 * Math.PI / 60 / 60 * scope.autoRotateSpeed;
}
}
function getZoomScale() {
function getZoomScale() {
复制
已复制
复制
已复制
return Math.pow( 0.95, scope.
userZ
oomSpeed );
return Math.pow( 0.95, scope.
z
oomSpeed );
}
}
function onMouseDown( event ) {
function onMouseDown( event ) {
if ( scope.enabled === false ) return;
if ( scope.enabled === false ) return;
复制
已复制
复制
已复制
if ( scope.userRotate === false ) return;
event.preventDefault();
event.preventDefault();
复制
已复制
复制
已复制
if ( state === STATE.NONE )
if ( event.button === 0 )
{
{
if ( scope.noRotate === true
)
return;
if ( event.button === 0 )
state = STATE.ROTATE;
if ( event.button === 1 )
state = STATE.ZOOM;
if ( event.button === 2 )
state = STATE.PAN;
}
if ( state === STATE.ROTATE
)
{
复制
已复制
复制
已复制
//
state = STATE.ROTATE;
state = STATE.ROTATE;
rotateStart.set( event.clientX, event.clientY );
rotateStart.set( event.clientX, event.clientY );
复制
已复制
复制
已复制
} else if (
state
===
STATE.ZOOM
) {
} else if (
event.button
===
1
) {
if ( scope.noZoom === true ) return;
复制
已复制
复制
已复制
//
state = STATE.
ZOOM
;
state = STATE.
DOLLY
;
复制
已复制
复制
已复制
zoomStart
.set( event.clientX, event.clientY );
dollyStart
.set( event.clientX, event.clientY );
复制
已复制
复制
已复制
} else if (
state
===
STATE.PAN
) {
} else if (
event.button
===
2
) {
if ( scope.noPan === true ) return;
复制
已复制
复制
已复制
//
state = STATE.PAN;
state = STATE.PAN;
panStart.set( event.clientX, event.clientY );
}
}
document.addEventListener( 'mousemove', onMouseMove, false );
document.addEventListener( 'mousemove', onMouseMove, false );
document.addEventListener( 'mouseup', onMouseUp, false );
document.addEventListener( 'mouseup', onMouseUp, false );
复制
已复制
复制
已复制
scope.dispatchEvent( startEvent );
}
}
function onMouseMove( event ) {
function onMouseMove( event ) {
if ( scope.enabled === false ) return;
if ( scope.enabled === false ) return;
event.preventDefault();
event.preventDefault();
复制
已复制
复制
已复制
var element = scope.domElement === document ? scope.domElement.body : scope.domElement;
if ( state === STATE.ROTATE ) {
if ( state === STATE.ROTATE ) {
复制
已复制
复制
已复制
if ( scope.noRotate === true ) return;
rotateEnd.set( event.clientX, event.clientY );
rotateEnd.set( event.clientX, event.clientY );
rotateDelta.subVectors( rotateEnd, rotateStart );
rotateDelta.subVectors( rotateEnd, rotateStart );
复制
已复制
复制
已复制
scope.rotateLeft( 2 * Math.PI * rotateDelta.x /
PIXELS_PER_ROUND
* scope.
userR
otateSpeed );
// rotating across whole screen goes 360 degrees around
scope.rotateUp( 2 * Math.PI * rotateDelta.y /
PIXELS_PER_ROUND
* scope.
userR
otateSpeed );
scope.rotateLeft( 2 * Math.PI * rotateDelta.x /
element.clientWidth
* scope.
r
otateSpeed );
// rotating up and down along whole screen attempts to go 360, but limited to 180
scope.rotateUp( 2 * Math.PI * rotateDelta.y /
element.clientHeight
* scope.
r
otateSpeed );
rotateStart.copy( rotateEnd );
rotateStart.copy( rotateEnd );
复制
已复制
复制
已复制
} else if ( state === STATE.
ZOOM
) {
} else if ( state === STATE.
DOLLY
) {
复制
已复制
复制
已复制
zoomEnd.set( event.clientX, event.clientY );
if ( scope.noZoom === true ) return;
zoomDelta.subVectors( zoomEnd, zoomStart );
复制
已复制
复制
已复制
if ( zoomDelta.y > 0 ) {
dollyEnd.set( event.clientX, event.clientY );
dollyDelta.subVectors( dollyEnd, dollyStart );
复制
已复制
复制
已复制
scope.
zoomIn
();
if ( dollyDelta.y > 0 ) {
scope.
dollyIn
();
} else {
} else {
复制
已复制
复制
已复制
scope.
zoomOut
();
scope.
dollyOut
();
}
}
复制
已复制
复制
已复制
zoomStart
.copy(
zoomEnd
);
dollyStart
.copy(
dollyEnd
);
} else if ( state === STATE.PAN ) {
} else if ( state === STATE.PAN ) {
复制
已复制
复制
已复制
var movementX = event.movementX || event.mozMovementX || event.webkitMovementX || 0;
if ( scope.noPan === true ) return;
var movementY = event.movementY || event.mozMovementY || event.webkitMovementY || 0;
复制
已复制
复制
已复制
scope.pan( new THREE.Vector3( - movementX, movementY, 0 ) );
panEnd.set( event.clientX, event.clientY );
panDelta.subVectors( panEnd, panStart );
scope.pan( panDelta.x, panDelta.y );
panStart.copy( panEnd );
}
}
复制
已复制
复制
已复制
scope.update();
}
}
复制
已复制
复制
已复制
function onMouseUp(
event
) {
function onMouseUp(
/*
event
*/
) {
if ( scope.enabled === false ) return;
if ( scope.enabled === false ) return;
复制
已复制
复制
已复制
if ( scope.userRotate === false ) return;
document.removeEventListener( 'mousemove', onMouseMove, false );
document.removeEventListener( 'mousemove', onMouseMove, false );
document.removeEventListener( 'mouseup', onMouseUp, false );
document.removeEventListener( 'mouseup', onMouseUp, false );
复制
已复制
复制
已复制
scope.dispatchEvent( endEvent );
state = STATE.NONE;
state = STATE.NONE;
}
}
function onMouseWheel( event ) {
function onMouseWheel( event ) {
复制
已复制
复制
已复制
if ( scope.enabled === false
) return;
if ( scope.enabled === false
||
scope.
noZoom
===
true
) return;
if (
scope.
userZoom
===
false
) return;
event.preventDefault();
event.stopPropagation();
var delta = 0;
var delta = 0;
复制
已复制
复制
已复制
if ( event.wheelDelta
) { // WebKit / Opera / Explorer 9
if ( event.wheelDelta
!== undefined
) { // WebKit / Opera / Explorer 9
delta = event.wheelDelta;
delta = event.wheelDelta;
复制
已复制
复制
已复制
} else if ( event.detail
) { // Firefox
} else if ( event.detail
!== undefined
) { // Firefox
delta = - event.detail;
delta = - event.detail;
}
}
if ( delta > 0 ) {
if ( delta > 0 ) {
复制
已复制
复制
已复制
scope.
zoomOut
();
scope.
dollyOut
();
} else {
} else {
复制
已复制
复制
已复制
scope.
zoomIn
();
scope.
dollyIn
();
}
}
复制
已复制
复制
已复制
scope.update();
scope.dispatchEvent( startEvent );
scope.dispatchEvent( endEvent );
}
}
function onKeyDown( event ) {
function onKeyDown( event ) {
复制
已复制
复制
已复制
if ( scope.enabled === false
) return;
if ( scope.enabled === false
|| scope.noKeys === true ||
scope.
noPan
===
true
) return;
if (
scope.
userPan
===
false
) return;
switch ( event.keyCode ) {
switch ( event.keyCode ) {
复制
已复制
复制
已复制
/*
case scope.keys.UP:
case scope.keys.UP:
scope.pan(
new THREE.Vector3(
0,
1, 0 )
);
scope.pan(
0,
scope.keyPanSpeed
);
scope.update();
break;
break;
复制
已复制
复制
已复制
case scope.keys.BOTTOM:
case scope.keys.BOTTOM:
复制
已复制
复制
已复制
scope.pan(
new THREE.Vector3(
0, -
1, 0 )
);
scope.pan(
0, -
scope.keyPanSpeed
);
scope.update();
break;
break;
复制
已复制
复制
已复制
case scope.keys.LEFT:
case scope.keys.LEFT:
复制
已复制
复制
已复制
scope.pan(
new THREE.Vector3( - 1, 0
, 0 )
);
scope.pan(
scope.keyPanSpeed
, 0 )
;
scope.update(
);
break;
break;
复制
已复制
复制
已复制
case scope.keys.RIGHT:
case scope.keys.RIGHT:
复制
已复制
复制
已复制
scope.pan(
new THREE.Vector3( 1, 0
, 0 )
);
scope.pan(
- scope.keyPanSpeed
, 0 )
;
scope.update(
);
break;
break;
复制
已复制
复制
已复制
*/
case scope.keys.ROTATE:
}
state = STATE.
ROTATE;
}
function touchstart( event ) {
if ( scope.enabled === false ) return;
switch ( event.touches.length ) {
case 1: // one-fingered touch: rotate
if ( scope.noRotate === true ) return;
state = STATE.TOUCH_
ROTATE;
rotateStart.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY );
break;
break;
复制
已复制
复制
已复制
case
scope.
keys.ZOOM:
state = STATE.
ZOOM;
case
2: // two-fingered touch: dolly
if (
scope.
noZoom === true ) return;
state = STATE.
TOUCH_DOLLY;
var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX;
var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY;
var distance = Math.sqrt( dx * dx + dy * dy );
dollyStart.set( 0, distance );
break;
break;
复制
已复制
复制
已复制
case
scope.
keys.PAN:
state = STATE.
PAN;
case
3: // three-fingered touch: pan
if (
scope.
noPan === true ) return;
state = STATE.
TOUCH_
PAN;
panStart.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY );
break;
break;
复制
已复制
复制
已复制
default:
state = STATE.NONE;
}
}
复制
已复制
复制
已复制
scope.dispatchEvent( startEvent );
}
}
复制
已复制
复制
已复制
function onKeyUp( event ) {
复制
已复制
复制
已复制
switch
( event
.keyCode
) {
function touchmove
( event
) {
复制
已复制
复制
已复制
case scope.keys.ROTATE:
if ( scope.enabled === false ) return;
case scope.keys.ZOOM:
case scope.keys.PAN:
event.preventDefault();
event.stopPropagation();
var element = scope.domElement === document ? scope.domElement.body : scope.domElement;
switch ( event.touches.length ) {
case 1: // one-fingered touch: rotate
if ( scope.noRotate === true ) return;
if ( state !== STATE.TOUCH_ROTATE ) return;
rotateEnd.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY );
rotateDelta.subVectors( rotateEnd, rotateStart );
// rotating across whole screen goes 360 degrees around
scope.rotateLeft( 2 * Math.PI * rotateDelta.x / element.clientWidth * scope.rotateSpeed );
// rotating up and down along whole screen attempts to go 360, but limited to 180
scope.rotateUp( 2 * Math.PI * rotateDelta.y / element.clientHeight * scope.rotateSpeed );
rotateStart.copy( rotateEnd );
scope.update();
break;
case 2: // two-fingered touch: dolly
if ( scope.noZoom === true ) return;
if ( state !== STATE.TOUCH_DOLLY ) return;
var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX;
var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY;
var distance = Math.sqrt( dx * dx + dy * dy );
dollyEnd.set( 0, distance );
dollyDelta.subVectors( dollyEnd, dollyStart );
if ( dollyDelta.y > 0 ) {
scope.dollyOut();
} else {
scope.dollyIn();
}
dollyStart.copy( dollyEnd );
scope.update();
break;
case 3: // three-fingered touch: pan
if ( scope.noPan === true ) return;
if ( state !== STATE.TOUCH_PAN ) return;
panEnd.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY );
panDelta.subVectors( panEnd, panStart );
scope.pan( panDelta.x, panDelta.y );
panStart.copy( panEnd );
scope.update();
break;
default:
state = STATE.NONE;
state = STATE.NONE;
复制
已复制
复制
已复制
break;
}
}
}
}
复制
已复制
复制
已复制
function touchend( /* event */ ) {
if ( scope.enabled === false ) return;
scope.dispatchEvent( endEvent );
state = STATE.NONE;
}
this.domElement.addEventListener( 'contextmenu', function ( event ) { event.preventDefault(); }, false );
this.domElement.addEventListener( 'contextmenu', function ( event ) { event.preventDefault(); }, false );
this.domElement.addEventListener( 'mousedown', onMouseDown, false );
this.domElement.addEventListener( 'mousedown', onMouseDown, false );
this.domElement.addEventListener( 'mousewheel', onMouseWheel, false );
this.domElement.addEventListener( 'mousewheel', onMouseWheel, false );
this.domElement.addEventListener( 'DOMMouseScroll', onMouseWheel, false ); // firefox
this.domElement.addEventListener( 'DOMMouseScroll', onMouseWheel, false ); // firefox
复制
已复制
复制
已复制
this.domElement.addEventListener( 'touchstart', touchstart, false );
this.domElement.addEventListener( 'touchend', touchend, false );
this.domElement.addEventListener( 'touchmove', touchmove, false );
window.addEventListener( 'keydown', onKeyDown, false );
window.addEventListener( 'keydown', onKeyDown, false );
复制
已复制
复制
已复制
window.addEventListener( 'keyup', onKeyUp, false
);
// force an update at start
this.update(
);
};
};
THREE.OrbitControls.prototype = Object.create( THREE.EventDispatcher.prototype );
THREE.OrbitControls.prototype = Object.create( THREE.EventDispatcher.prototype );
已保存差异
原始文本
打开文件
/** * @author qiao / https://github.com/qiao * @author mrdoob / http://mrdoob.com * @author alteredq / http://alteredqualia.com/ * @author WestLangley / http://github.com/WestLangley */ THREE.OrbitControls = function ( object, domElement ) { this.object = object; this.domElement = ( domElement !== undefined ) ? domElement : document; // API this.enabled = true; this.center = new THREE.Vector3(); this.userZoom = true; this.userZoomSpeed = 1.0; this.userRotate = true; this.userRotateSpeed = 1.0; this.userPan = true; this.userPanSpeed = 2.0; this.autoRotate = false; this.autoRotateSpeed = 2.0; // 30 seconds per round when fps is 60 this.minPolarAngle = 0; // radians this.maxPolarAngle = Math.PI; // radians this.minDistance = 0; this.maxDistance = Infinity; // 65 /*A*/, 83 /*S*/, 68 /*D*/ this.keys = { LEFT: 37, UP: 38, RIGHT: 39, BOTTOM: 40, ROTATE: 65, ZOOM: 83, PAN: 68 }; // internals var scope = this; var EPS = 0.000001; var PIXELS_PER_ROUND = 1800; var rotateStart = new THREE.Vector2(); var rotateEnd = new THREE.Vector2(); var rotateDelta = new THREE.Vector2(); var zoomStart = new THREE.Vector2(); var zoomEnd = new THREE.Vector2(); var zoomDelta = new THREE.Vector2(); var phiDelta = 0; var thetaDelta = 0; var scale = 1; var lastPosition = new THREE.Vector3(); var STATE = { NONE: -1, ROTATE: 0, ZOOM: 1, PAN: 2 }; var state = STATE.NONE; // events var changeEvent = { type: 'change' }; this.rotateLeft = function ( angle ) { if ( angle === undefined ) { angle = getAutoRotationAngle(); } thetaDelta -= angle; }; this.rotateRight = function ( angle ) { if ( angle === undefined ) { angle = getAutoRotationAngle(); } thetaDelta += angle; }; this.rotateUp = function ( angle ) { if ( angle === undefined ) { angle = getAutoRotationAngle(); } phiDelta -= angle; }; this.rotateDown = function ( angle ) { if ( angle === undefined ) { angle = getAutoRotationAngle(); } phiDelta += angle; }; this.zoomIn = function ( zoomScale ) { if ( zoomScale === undefined ) { zoomScale = getZoomScale(); } scale /= zoomScale; }; this.zoomOut = function ( zoomScale ) { if ( zoomScale === undefined ) { zoomScale = getZoomScale(); } scale *= zoomScale; }; this.pan = function ( distance ) { distance.transformDirection( this.object.matrix ); distance.multiplyScalar( scope.userPanSpeed ); this.object.position.add( distance ); this.center.add( distance ); }; this.update = function () { var position = this.object.position; var offset = position.clone().sub( this.center ); // angle from z-axis around y-axis var theta = Math.atan2( offset.x, offset.z ); // angle from y-axis var phi = Math.atan2( Math.sqrt( offset.x * offset.x + offset.z * offset.z ), offset.y ); if ( this.autoRotate ) { this.rotateLeft( getAutoRotationAngle() ); } theta += thetaDelta; phi += phiDelta; // restrict phi to be between desired limits phi = Math.max( this.minPolarAngle, Math.min( this.maxPolarAngle, phi ) ); // restrict phi to be betwee EPS and PI-EPS phi = Math.max( EPS, Math.min( Math.PI - EPS, phi ) ); var radius = offset.length() * scale; // restrict radius to be between desired limits radius = Math.max( this.minDistance, Math.min( this.maxDistance, radius ) ); offset.x = radius * Math.sin( phi ) * Math.sin( theta ); offset.y = radius * Math.cos( phi ); offset.z = radius * Math.sin( phi ) * Math.cos( theta ); position.copy( this.center ).add( offset ); this.object.lookAt( this.center ); thetaDelta = 0; phiDelta = 0; scale = 1; if ( lastPosition.distanceTo( this.object.position ) > 0 ) { this.dispatchEvent( changeEvent ); lastPosition.copy( this.object.position ); } }; function getAutoRotationAngle() { return 2 * Math.PI / 60 / 60 * scope.autoRotateSpeed; } function getZoomScale() { return Math.pow( 0.95, scope.userZoomSpeed ); } function onMouseDown( event ) { if ( scope.enabled === false ) return; if ( scope.userRotate === false ) return; event.preventDefault(); if ( state === STATE.NONE ) { if ( event.button === 0 ) state = STATE.ROTATE; if ( event.button === 1 ) state = STATE.ZOOM; if ( event.button === 2 ) state = STATE.PAN; } if ( state === STATE.ROTATE ) { //state = STATE.ROTATE; rotateStart.set( event.clientX, event.clientY ); } else if ( state === STATE.ZOOM ) { //state = STATE.ZOOM; zoomStart.set( event.clientX, event.clientY ); } else if ( state === STATE.PAN ) { //state = STATE.PAN; } document.addEventListener( 'mousemove', onMouseMove, false ); document.addEventListener( 'mouseup', onMouseUp, false ); } function onMouseMove( event ) { if ( scope.enabled === false ) return; event.preventDefault(); if ( state === STATE.ROTATE ) { rotateEnd.set( event.clientX, event.clientY ); rotateDelta.subVectors( rotateEnd, rotateStart ); scope.rotateLeft( 2 * Math.PI * rotateDelta.x / PIXELS_PER_ROUND * scope.userRotateSpeed ); scope.rotateUp( 2 * Math.PI * rotateDelta.y / PIXELS_PER_ROUND * scope.userRotateSpeed ); rotateStart.copy( rotateEnd ); } else if ( state === STATE.ZOOM ) { zoomEnd.set( event.clientX, event.clientY ); zoomDelta.subVectors( zoomEnd, zoomStart ); if ( zoomDelta.y > 0 ) { scope.zoomIn(); } else { scope.zoomOut(); } zoomStart.copy( zoomEnd ); } else if ( state === STATE.PAN ) { var movementX = event.movementX || event.mozMovementX || event.webkitMovementX || 0; var movementY = event.movementY || event.mozMovementY || event.webkitMovementY || 0; scope.pan( new THREE.Vector3( - movementX, movementY, 0 ) ); } } function onMouseUp( event ) { if ( scope.enabled === false ) return; if ( scope.userRotate === false ) return; document.removeEventListener( 'mousemove', onMouseMove, false ); document.removeEventListener( 'mouseup', onMouseUp, false ); state = STATE.NONE; } function onMouseWheel( event ) { if ( scope.enabled === false ) return; if ( scope.userZoom === false ) return; var delta = 0; if ( event.wheelDelta ) { // WebKit / Opera / Explorer 9 delta = event.wheelDelta; } else if ( event.detail ) { // Firefox delta = - event.detail; } if ( delta > 0 ) { scope.zoomOut(); } else { scope.zoomIn(); } } function onKeyDown( event ) { if ( scope.enabled === false ) return; if ( scope.userPan === false ) return; switch ( event.keyCode ) { /*case scope.keys.UP: scope.pan( new THREE.Vector3( 0, 1, 0 ) ); break; case scope.keys.BOTTOM: scope.pan( new THREE.Vector3( 0, - 1, 0 ) ); break; case scope.keys.LEFT: scope.pan( new THREE.Vector3( - 1, 0, 0 ) ); break; case scope.keys.RIGHT: scope.pan( new THREE.Vector3( 1, 0, 0 ) ); break; */ case scope.keys.ROTATE: state = STATE.ROTATE; break; case scope.keys.ZOOM: state = STATE.ZOOM; break; case scope.keys.PAN: state = STATE.PAN; break; } } function onKeyUp( event ) { switch ( event.keyCode ) { case scope.keys.ROTATE: case scope.keys.ZOOM: case scope.keys.PAN: state = STATE.NONE; break; } } this.domElement.addEventListener( 'contextmenu', function ( event ) { event.preventDefault(); }, false ); this.domElement.addEventListener( 'mousedown', onMouseDown, false ); this.domElement.addEventListener( 'mousewheel', onMouseWheel, false ); this.domElement.addEventListener( 'DOMMouseScroll', onMouseWheel, false ); // firefox window.addEventListener( 'keydown', onKeyDown, false ); window.addEventListener( 'keyup', onKeyUp, false ); }; THREE.OrbitControls.prototype = Object.create( THREE.EventDispatcher.prototype );
更改后文本
打开文件
/** * @author qiao / https://github.com/qiao * @author mrdoob / http://mrdoob.com * @author alteredq / http://alteredqualia.com/ * @author WestLangley / http://github.com/WestLangley * @author erich666 / http://erichaines.com */ /*global THREE, console */ // This set of controls performs orbiting, dollying (zooming), and panning. It maintains // the "up" direction as +Y, unlike the TrackballControls. Touch on tablet and phones is // supported. // // Orbit - left mouse / touch: one finger move // Zoom - middle mouse, or mousewheel / touch: two finger spread or squish // Pan - right mouse, or arrow keys / touch: three finter swipe // // This is a drop-in replacement for (most) TrackballControls used in examples. // That is, include this js file and wherever you see: // controls = new THREE.TrackballControls( camera ); // controls.target.z = 150; // Simple substitute "OrbitControls" and the control should work as-is. THREE.OrbitControls = function ( object, domElement ) { this.object = object; this.domElement = ( domElement !== undefined ) ? domElement : document; // API // Set to false to disable this control this.enabled = true; // "target" sets the location of focus, where the control orbits around // and where it pans with respect to. this.target = new THREE.Vector3(); // center is old, deprecated; use "target" instead this.center = this.target; // This option actually enables dollying in and out; left as "zoom" for // backwards compatibility this.noZoom = false; this.zoomSpeed = 1.0; // Limits to how far you can dolly in and out this.minDistance = 0; this.maxDistance = Infinity; // Set to true to disable this control this.noRotate = false; this.rotateSpeed = 1.0; // Set to true to disable this control this.noPan = false; this.keyPanSpeed = 7.0; // pixels moved per arrow key push // Set to true to automatically rotate around the target this.autoRotate = false; this.autoRotateSpeed = 2.0; // 30 seconds per round when fps is 60 // How far you can orbit vertically, upper and lower limits. // Range is 0 to Math.PI radians. this.minPolarAngle = 0; // radians this.maxPolarAngle = Math.PI; // radians // Set to true to disable use of the keys this.noKeys = false; // The four arrow keys this.keys = { LEFT: 37, UP: 38, RIGHT: 39, BOTTOM: 40 }; //////////// // internals var scope = this; var EPS = 0.000001; var rotateStart = new THREE.Vector2(); var rotateEnd = new THREE.Vector2(); var rotateDelta = new THREE.Vector2(); var panStart = new THREE.Vector2(); var panEnd = new THREE.Vector2(); var panDelta = new THREE.Vector2(); var panOffset = new THREE.Vector3(); var offset = new THREE.Vector3(); var dollyStart = new THREE.Vector2(); var dollyEnd = new THREE.Vector2(); var dollyDelta = new THREE.Vector2(); var phiDelta = 0; var thetaDelta = 0; var scale = 1; var pan = new THREE.Vector3(); var lastPosition = new THREE.Vector3(); var lastQuaternion = new THREE.Quaternion(); var STATE = { NONE : -1, ROTATE : 0, DOLLY : 1, PAN : 2, TOUCH_ROTATE : 3, TOUCH_DOLLY : 4, TOUCH_PAN : 5 }; var state = STATE.NONE; // for reset this.target0 = this.target.clone(); this.position0 = this.object.position.clone(); // so camera.up is the orbit axis var quat = new THREE.Quaternion().setFromUnitVectors( object.up, new THREE.Vector3( 0, 1, 0 ) ); var quatInverse = quat.clone().inverse(); // events var changeEvent = { type: 'change' }; var startEvent = { type: 'start'}; var endEvent = { type: 'end'}; this.rotateLeft = function ( angle ) { if ( angle === undefined ) { angle = getAutoRotationAngle(); } thetaDelta -= angle; }; this.rotateUp = function ( angle ) { if ( angle === undefined ) { angle = getAutoRotationAngle(); } phiDelta -= angle; }; // pass in distance in world space to move left this.panLeft = function ( distance ) { var te = this.object.matrix.elements; // get X column of matrix panOffset.set( te[ 0 ], te[ 1 ], te[ 2 ] ); panOffset.multiplyScalar( - distance ); pan.add( panOffset ); }; // pass in distance in world space to move up this.panUp = function ( distance ) { var te = this.object.matrix.elements; // get Y column of matrix panOffset.set( te[ 4 ], te[ 5 ], te[ 6 ] ); panOffset.multiplyScalar( distance ); pan.add( panOffset ); }; // pass in x,y of change desired in pixel space, // right and down are positive this.pan = function ( deltaX, deltaY ) { var element = scope.domElement === document ? scope.domElement.body : scope.domElement; if ( scope.object.fov !== undefined ) { // perspective var position = scope.object.position; var offset = position.clone().sub( scope.target ); var targetDistance = offset.length(); // half of the fov is center to top of screen targetDistance *= Math.tan( ( scope.object.fov / 2 ) * Math.PI / 180.0 ); // we actually don't use screenWidth, since perspective camera is fixed to screen height scope.panLeft( 2 * deltaX * targetDistance / element.clientHeight ); scope.panUp( 2 * deltaY * targetDistance / element.clientHeight ); } else if ( scope.object.top !== undefined ) { // orthographic scope.panLeft( deltaX * (scope.object.right - scope.object.left) / element.clientWidth ); scope.panUp( deltaY * (scope.object.top - scope.object.bottom) / element.clientHeight ); } else { // camera neither orthographic or perspective console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - pan disabled.' ); } }; this.dollyIn = function ( dollyScale ) { if ( dollyScale === undefined ) { dollyScale = getZoomScale(); } scale /= dollyScale; }; this.dollyOut = function ( dollyScale ) { if ( dollyScale === undefined ) { dollyScale = getZoomScale(); } scale *= dollyScale; }; this.update = function () { var position = this.object.position; offset.copy( position ).sub( this.target ); // rotate offset to "y-axis-is-up" space offset.applyQuaternion( quat ); // angle from z-axis around y-axis var theta = Math.atan2( offset.x, offset.z ); // angle from y-axis var phi = Math.atan2( Math.sqrt( offset.x * offset.x + offset.z * offset.z ), offset.y ); if ( this.autoRotate ) { this.rotateLeft( getAutoRotationAngle() ); } theta += thetaDelta; phi += phiDelta; // restrict phi to be between desired limits phi = Math.max( this.minPolarAngle, Math.min( this.maxPolarAngle, phi ) ); // restrict phi to be betwee EPS and PI-EPS phi = Math.max( EPS, Math.min( Math.PI - EPS, phi ) ); var radius = offset.length() * scale; // restrict radius to be between desired limits radius = Math.max( this.minDistance, Math.min( this.maxDistance, radius ) ); // move target to panned location this.target.add( pan ); offset.x = radius * Math.sin( phi ) * Math.sin( theta ); offset.y = radius * Math.cos( phi ); offset.z = radius * Math.sin( phi ) * Math.cos( theta ); // rotate offset back to "camera-up-vector-is-up" space offset.applyQuaternion( quatInverse ); position.copy( this.target ).add( offset ); this.object.lookAt( this.target ); thetaDelta = 0; phiDelta = 0; scale = 1; pan.set( 0, 0, 0 ); // update condition is: // min(camera displacement, camera rotation in radians)^2 > EPS // using small-angle approximation cos(x/2) = 1 - x^2 / 8 if ( lastPosition.distanceToSquared( this.object.position ) > EPS || 8 * (1 - lastQuaternion.dot(this.object.quaternion)) > EPS ) { this.dispatchEvent( changeEvent ); lastPosition.copy( this.object.position ); lastQuaternion.copy (this.object.quaternion ); } }; this.reset = function () { state = STATE.NONE; this.target.copy( this.target0 ); this.object.position.copy( this.position0 ); this.update(); }; function getAutoRotationAngle() { return 2 * Math.PI / 60 / 60 * scope.autoRotateSpeed; } function getZoomScale() { return Math.pow( 0.95, scope.zoomSpeed ); } function onMouseDown( event ) { if ( scope.enabled === false ) return; event.preventDefault(); if ( event.button === 0 ) { if ( scope.noRotate === true ) return; state = STATE.ROTATE; rotateStart.set( event.clientX, event.clientY ); } else if ( event.button === 1 ) { if ( scope.noZoom === true ) return; state = STATE.DOLLY; dollyStart.set( event.clientX, event.clientY ); } else if ( event.button === 2 ) { if ( scope.noPan === true ) return; state = STATE.PAN; panStart.set( event.clientX, event.clientY ); } document.addEventListener( 'mousemove', onMouseMove, false ); document.addEventListener( 'mouseup', onMouseUp, false ); scope.dispatchEvent( startEvent ); } function onMouseMove( event ) { if ( scope.enabled === false ) return; event.preventDefault(); var element = scope.domElement === document ? scope.domElement.body : scope.domElement; if ( state === STATE.ROTATE ) { if ( scope.noRotate === true ) return; rotateEnd.set( event.clientX, event.clientY ); rotateDelta.subVectors( rotateEnd, rotateStart ); // rotating across whole screen goes 360 degrees around scope.rotateLeft( 2 * Math.PI * rotateDelta.x / element.clientWidth * scope.rotateSpeed ); // rotating up and down along whole screen attempts to go 360, but limited to 180 scope.rotateUp( 2 * Math.PI * rotateDelta.y / element.clientHeight * scope.rotateSpeed ); rotateStart.copy( rotateEnd ); } else if ( state === STATE.DOLLY ) { if ( scope.noZoom === true ) return; dollyEnd.set( event.clientX, event.clientY ); dollyDelta.subVectors( dollyEnd, dollyStart ); if ( dollyDelta.y > 0 ) { scope.dollyIn(); } else { scope.dollyOut(); } dollyStart.copy( dollyEnd ); } else if ( state === STATE.PAN ) { if ( scope.noPan === true ) return; panEnd.set( event.clientX, event.clientY ); panDelta.subVectors( panEnd, panStart ); scope.pan( panDelta.x, panDelta.y ); panStart.copy( panEnd ); } scope.update(); } function onMouseUp( /* event */ ) { if ( scope.enabled === false ) return; document.removeEventListener( 'mousemove', onMouseMove, false ); document.removeEventListener( 'mouseup', onMouseUp, false ); scope.dispatchEvent( endEvent ); state = STATE.NONE; } function onMouseWheel( event ) { if ( scope.enabled === false || scope.noZoom === true ) return; event.preventDefault(); event.stopPropagation(); var delta = 0; if ( event.wheelDelta !== undefined ) { // WebKit / Opera / Explorer 9 delta = event.wheelDelta; } else if ( event.detail !== undefined ) { // Firefox delta = - event.detail; } if ( delta > 0 ) { scope.dollyOut(); } else { scope.dollyIn(); } scope.update(); scope.dispatchEvent( startEvent ); scope.dispatchEvent( endEvent ); } function onKeyDown( event ) { if ( scope.enabled === false || scope.noKeys === true || scope.noPan === true ) return; switch ( event.keyCode ) { case scope.keys.UP: scope.pan( 0, scope.keyPanSpeed ); scope.update(); break; case scope.keys.BOTTOM: scope.pan( 0, - scope.keyPanSpeed ); scope.update(); break; case scope.keys.LEFT: scope.pan( scope.keyPanSpeed, 0 ); scope.update(); break; case scope.keys.RIGHT: scope.pan( - scope.keyPanSpeed, 0 ); scope.update(); break; } } function touchstart( event ) { if ( scope.enabled === false ) return; switch ( event.touches.length ) { case 1: // one-fingered touch: rotate if ( scope.noRotate === true ) return; state = STATE.TOUCH_ROTATE; rotateStart.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ); break; case 2: // two-fingered touch: dolly if ( scope.noZoom === true ) return; state = STATE.TOUCH_DOLLY; var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX; var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY; var distance = Math.sqrt( dx * dx + dy * dy ); dollyStart.set( 0, distance ); break; case 3: // three-fingered touch: pan if ( scope.noPan === true ) return; state = STATE.TOUCH_PAN; panStart.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ); break; default: state = STATE.NONE; } scope.dispatchEvent( startEvent ); } function touchmove( event ) { if ( scope.enabled === false ) return; event.preventDefault(); event.stopPropagation(); var element = scope.domElement === document ? scope.domElement.body : scope.domElement; switch ( event.touches.length ) { case 1: // one-fingered touch: rotate if ( scope.noRotate === true ) return; if ( state !== STATE.TOUCH_ROTATE ) return; rotateEnd.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ); rotateDelta.subVectors( rotateEnd, rotateStart ); // rotating across whole screen goes 360 degrees around scope.rotateLeft( 2 * Math.PI * rotateDelta.x / element.clientWidth * scope.rotateSpeed ); // rotating up and down along whole screen attempts to go 360, but limited to 180 scope.rotateUp( 2 * Math.PI * rotateDelta.y / element.clientHeight * scope.rotateSpeed ); rotateStart.copy( rotateEnd ); scope.update(); break; case 2: // two-fingered touch: dolly if ( scope.noZoom === true ) return; if ( state !== STATE.TOUCH_DOLLY ) return; var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX; var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY; var distance = Math.sqrt( dx * dx + dy * dy ); dollyEnd.set( 0, distance ); dollyDelta.subVectors( dollyEnd, dollyStart ); if ( dollyDelta.y > 0 ) { scope.dollyOut(); } else { scope.dollyIn(); } dollyStart.copy( dollyEnd ); scope.update(); break; case 3: // three-fingered touch: pan if ( scope.noPan === true ) return; if ( state !== STATE.TOUCH_PAN ) return; panEnd.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ); panDelta.subVectors( panEnd, panStart ); scope.pan( panDelta.x, panDelta.y ); panStart.copy( panEnd ); scope.update(); break; default: state = STATE.NONE; } } function touchend( /* event */ ) { if ( scope.enabled === false ) return; scope.dispatchEvent( endEvent ); state = STATE.NONE; } this.domElement.addEventListener( 'contextmenu', function ( event ) { event.preventDefault(); }, false ); this.domElement.addEventListener( 'mousedown', onMouseDown, false ); this.domElement.addEventListener( 'mousewheel', onMouseWheel, false ); this.domElement.addEventListener( 'DOMMouseScroll', onMouseWheel, false ); // firefox this.domElement.addEventListener( 'touchstart', touchstart, false ); this.domElement.addEventListener( 'touchend', touchend, false ); this.domElement.addEventListener( 'touchmove', touchmove, false ); window.addEventListener( 'keydown', onKeyDown, false ); // force an update at start this.update(); }; THREE.OrbitControls.prototype = Object.create( THREE.EventDispatcher.prototype );
查找差异