相机
CameraControls 用于对相机进行控制操作。
通过 app.cameraControl 来访问.
注意
当map3d做为vjmap的一个3D图层展示时,因为相机是与vjmap二维地图的相机保持同步的,所以相机操作只能通过vjmap的Map去操作相机。这种模式不创建相机控制器,app.cameraControl 为 undefined(调用其方法抛 TypeError);程序化设视角用 app.setCameraLookAt(position, lookAt)(地图模式内部转为 map.setFreeCameraOptions)或直接操作 vjmap 的 map。
示例
基本用法
let svc = new vjmap3d.Service(env.serviceUrl, env.accessToken);
let app = new vjmap3d.App(svc, {
container: "map", // 容器id
scene: { // 场景设置
gridHelper: { visible: true } // 是否显示坐标网格
}
})
const mesh = new THREE.Mesh(
new THREE.BoxGeometry( 1, 1, 1 ),
new THREE.MeshBasicMaterial( { color: 0xff0000, wireframe: true } )
);
app.scene.add( mesh );
let cameraControls = app.cameraControl;
const ui = await app.getConfigPane({ title: "相机操作", style: { width: "250px"}});
let gui = new vjmap3d.UiPanelJsonConfig();
gui.add(cameraControls, "enabled")
gui.add(cameraControls, "verticalDragToForward")
gui.add(cameraControls, "dollyToCursor")
gui.add(cameraControls, "dollyDragInverted")
gui.addButton('rotate theta 45deg' , () => cameraControls.rotate( 45 * THREE.MathUtils.DEG2RAD, 0, true ));
gui.addButton('rotate theta -90deg' , () => cameraControls.rotate( - 90 * THREE.MathUtils.DEG2RAD, 0, true ));
gui.addButton('rotate theta 360deg' , () => cameraControls.rotate( 360 * THREE.MathUtils.DEG2RAD, 0, true ));
gui.addButton('rotate phi 20deg' , () => cameraControls.rotate( 0, 20 * THREE.MathUtils.DEG2RAD, true ));
gui.addButton('pan( 0, 1 )' , () => cameraControls.pan( 1, 0, true));
gui.addButton('pan( -1, -1 )' , () => cameraControls.pan( - 1, - 1, true ));
gui.addButton('dolly 1' , () => cameraControls.dolly( 1, true ));
gui.addButton('dolly -1' , () => cameraControls.dolly( - 1, true ));
gui.addButton('zoom `camera.zoom / 2`' , () => cameraControls.zoom( app.camera.zoom / 2, true ));
gui.addButton('move to( 3, 5, 2 )' , () => cameraControls.moveTo( 3, 5, 2, true ));
gui.addButton('fit to the bounding box of the mesh' , () => cameraControls.fitToBox( mesh, true ))
gui.addButton('move to ( -5, 2, 1 )' , () => cameraControls.setPosition( - 5, 2, 1, true ));
gui.addButton('look at ( 3, 0, -3 )' , () => cameraControls.setTarget( 3, 0, -3, true ));
gui.addButton('move to ( 1, 2, 3 ), look at ( 1, 1, 0 )' , () => cameraControls.setLookAt( 1, 2, 3, 1, 1, 0, true ));
gui.addButton('move to somewhere between ( -2, 0, 0 ) -> ( 1, 1, 0 ) and ( 0, 2, 5 ) -> ( -1, 0, 0 )' , () => cameraControls.lerpLookAt( - 2, 0, 0, 1, 1, 0, 0, 2, 5, - 1, 0, 0, Math.random(), true ));
gui.addButton('shake' , () => cameraControls.shake( 1000, 10, 1, false ));
gui.addButton('reset' , () => cameraControls.reset( true ));
let state;
gui.addButton('saveState' , () => state = cameraControls.saveState());
gui.addButton('loadState' , () => {if(state) cameraControls.loadState( state )});
gui.toJson().forEach(c => ui.appendChild(c));
轨道旋转
CameraControls 使用球面坐标进行轨道旋转。
如果您的相机是 Y 轴向上,则方位角将是 y 轴旋转的角度,而极角将是垂直位置的角度。

Dolly指将镜头移近或远离主体, pan 则是平行主体移动镜头
Dolly 和 Zoom
- 缩放涉及改变镜头焦距。在 three.js 中,缩放实际上是改变相机 FOV,而相机是静止的(不会移动)。
- 移动摄影机通过物理移动相机来改变画面。
#特性
| 名称 | 类型 | 默认 | 描述 |
|---|---|---|---|
.camera |
`THREE.Perspective | THREE.Orthographic` | 不适用 |
.enabled |
boolean |
true |
控件是否启用。 |
.active |
boolean |
false |
true如果控件正在主动更新则返回。 |
.currentAction |
ACTION |
不适用 | 当前的 Getter ACTION。 |
.distance |
number |
不适用 | 当前距离。 |
.minDistance |
number |
Number.EPSILON |
镜头移动的最小距离。该值必须大于0 |
.maxDistance |
number |
Infinity |
镜头移动的最大距离。 |
.minZoom |
number |
0.01 |
最小相机变焦。 |
.maxZoom |
number |
Infinity |
最大相机变焦。 |
.polarAngle |
number |
不适用 | 当前极角(以弧度为单位)。 |
.minPolarAngle |
number |
0 |
以弧度为单位。 |
.maxPolarAngle |
number |
Math.PI |
以弧度为单位。 |
.azimuthAngle |
number |
不适用 | 当前方位角以弧度表示¹。 |
.minAzimuthAngle |
number |
-Infinity |
以弧度为单位。 |
.maxAzimuthAngle |
number |
Infinity |
以弧度为单位。 |
.boundaryFriction |
number |
0.0 |
边界的摩擦比。 |
.boundaryEnclosesCamera |
boolean |
false |
相机位置是否应该包含在边界内。 |
.smoothTime |
number |
0.25 |
达到目标的大致时间(以秒为单位)。值越小,达到目标越快。 |
.draggingSmoothTime |
number |
0.125 |
拖动时的平滑时间。 |
.azimuthRotateSpeed |
number |
1.0 |
方位旋转的速度。 |
.polarRotateSpeed |
number |
1.0 |
极地自转速度。 |
.dollySpeed |
number |
1.0 |
鼠标滚轮移动的速度。 |
.truckSpeed |
number |
2.0 |
拖动速度。 |
.verticalDragToForward |
boolean |
true |
.screenSpacePanning与three.js 的 OrbitControls相同。 |
.dollyToCursor |
boolean |
false |
true启用鼠标光标坐标的推拉功能。 |
.dollyDragInverted |
boolean |
false |
true通过拖动来移动或缩放时反转方向。 |
.interactiveArea |
DOMRect |
不适用 | 在 domElement 中设置拖动开始、触摸和滚轮启用区域。每个值都在和之间(0包括1),其中是屏幕的0左/上和右/下。1 |
.colliderMeshes |
array |
[] |
与相机发生碰撞的网格阵列。 |
.infinityDolly |
boolean |
false |
true启用 Infinity Dolly 的滚轮和夹点功能。将其与minDistance和maxDistance³ 一起使用。 |
.restThreshold |
number |
0.01 |
rest控制相机减速时事件触发的速度 |
- 每旋转360度,值都会增加
.azimuthAngle,是累积的。
360º = 360 * THREE.MathUtils.DEG2RAD = Math.PI * 2,720º = Math.PI * 4。 - 请注意,colliderMeshes 可能会降低性能。碰撞测试使用来自相机的 4 个射线发射器,因为近平面有 4 个角。
- 如果 Dolly 距离小于(或大于)
minDistance(或maxDistance),infinityDolly则将保持距离并推动目标位置。
事件
CameraControls 实例发出以下事件。
要订阅,请使用cameraControl.addEventListener( 'eventname', function )。
要取消订阅,请使用cameraControl.removeEventListener( 'eventname', function )。
| 事件名称 | 说明 |
|---|---|
'controlstart' |
当用户开始通过鼠标/触摸控制相机时。¹ |
'control' |
当用户控制相机(拖动)时。 |
'controlend' |
当用户结束控制相机时。¹ |
'transitionstart' |
当任何类型的转换开始时,无论是用户控制还是使用带有enableTransition = true |
'update' |
当相机位置更新时。 |
'wake' |
当相机开始移动时。 |
'rest' |
当相机移动低于.restThreshold²时。 |
'sleep' |
当相机停止移动时。 |
mouseButtons.wheel(鼠标滚轮控制)不发出'controlstart'。内部使用滚动事件,并且滚动事件间歇发生。这意味着无法检测到“开始”和“结束”'controlend'。mouseButtons.wheel- 由于阻尼,通常_会_在相机停止移动
sleep后几秒触发。如果您想在相机停止时执行某些操作(例如启用 UI、执行另一个转换),您可能需要该事件。可以使用参数进行微调。
用户输入设置
| 按钮 | 行为 |
|---|---|
mouseButtons.left |
CameraControls.ACTION.ROTATE* |
mouseButtons.right |
CameraControls.ACTION.ROTATE |
mouseButtons.wheel¹ |
CameraControls.ACTION.ROTATE |
mouseButtons.middle² |
CameraControls.ACTION.ROTATE |
- 鼠标滚轮事件用于在 Mac 上“上/下/左/右”滚动“上/下”
- 鼠标点击滚轮事件“按钮”
- * 是默认值。
- 的默认值为
mouseButtons.wheel:DOLLY对于透视相机。ZOOM对于正交相机,无法设置DOLLY。
| 移动端手指 | 行为 |
|---|---|
touches.one |
CameraControls.ACTION.TOUCH_ROTATE* |
touches.two |
ACTION.TOUCH_DOLLY_TRUCK |
touches.three |
ACTION.TOUCH_DOLLY_TRUCK |
- * 是默认值。
touches.two和的默认值为touches.three:TOUCH_DOLLY_TRUCK对于透视相机。TOUCH_ZOOM_TRUCK对于正交相机,无法设置TOUCH_DOLLY_TRUCK和TOUCH_DOLLY。
方法
rotate
旋转方位角(水平)和极角(垂直)。
每个值都添加到当前值。
| 名称 | 类型 | 描述 |
|---|---|---|
azimuthAngle |
number |
方位角旋转的角度。以弧度为单位。 |
polarAngle |
number |
极坐标旋转角度,单位为弧度。 |
enableTransition |
boolean |
是否平稳移动或立即移动 |
如果只想旋转一个轴,请为要旋转的轴设置一个角度,并0为另一个轴设置一个角度。
rotate( 20 * THREE.MathUtils.DEG2RAD, 0, true );
rotateAzimuthTo
将方位角(水平)旋转到给定角度并保持相同的极角(垂直)目标。
| 名称 | 类型 | 描述 |
|---|---|---|
azimuthAngle |
number |
方位角旋转的角度。以弧度为单位。 |
enableTransition |
boolean |
是否平稳移动或立即移动 |
rotatePolarTo
将极角(垂直)旋转到给定角度并保持相同的方位角(水平)目标。
| 名称 | 类型 | 描述 |
|---|---|---|
polarAngle |
number |
极坐标旋转角度,单位为弧度。 |
enableTransition |
boolean |
是否平稳移动或立即移动 |
rotateTo
将方位角(水平)和极角(垂直)旋转到给定的角度。
相机视图将绝对旋转到轨道轴上:
方位角
0º
\
90º -----+----- -90º
\
180º
0º 前、90º ( Math.PI / 2) 左、-90º ( - Math.PI / 2) 右、180º ( Math.PI) 后
极角
180º
|
90º
|
0º
极角 0 = 相机在目标正上方向下俯视;Math.PI / 2 = 水平视角;Math.PI = 相机在目标正下方仰视(看向天空)。上图的"180º 顶部 / 0º 底部"指的是视线方向(看天 / 看地),不是相机所在位置。
| 名称 | 类型 | 描述 |
|---|---|---|
azimuthAngle |
number |
方位角旋转至。以弧度为单位。 |
polarAngle |
number |
极坐标旋转角度至。以弧度为单位。 |
enableTransition |
boolean |
是否平稳移动或立即移动 |
dolly
移动相机位置。(指将镜头移近或远离主体进行缩放)
| 名称 | 类型 | 描述 |
|---|---|---|
distance |
number |
移动距离 |
enableTransition |
boolean |
是否平稳移动或立即移动 |
dollyTo
将摄影机位置移动至指定距离。(指将镜头移近或远离主体进行缩放)
| 名称 | 类型 | 描述 |
|---|---|---|
distance |
number |
移动距离 |
enableTransition |
boolean |
是否平稳移动或立即移动 |
dollyInFixed
拉近镜头,但不改变目标与相机之间的距离,而是移动目标位置。
为拉远镜头指定负值。
| 名称 | 类型 | 描述 |
|---|---|---|
distance |
number |
移动距离 |
enableTransition |
boolean |
是否平稳移动或立即移动 |
zoom
放大/缩小相机。该值添加到相机缩放。使用和
设置的限制.minZoom .maxZoom
| 名称 | 类型 | 描述 |
|---|---|---|
zoomStep |
number |
缩放比例 |
enableTransition |
boolean |
是否平稳移动或立即移动 |
您还可以使用camera.zoom属性来实现放大功能。
例如
const zoomIn = () => cameraControls.zoom( camera.zoom / 2, true );
const zoomOut = () => cameraControls.zoom( - camera.zoom / 2, true );
zoomTo
将相机放大/缩小至指定比例。该值会覆盖相机缩放。使用和
设置的限制.minZoom .maxZoom
| 名称 | 类型 | 描述 |
|---|---|---|
zoom |
number |
缩放比例 |
enableTransition |
boolean |
是否平稳移动或立即移动 |
pan
使用当前方位角平移相机。
| 名称 | 类型 | 描述 |
|---|---|---|
x |
number |
水平平移量 |
y |
number |
垂直平移量 |
enableTransition |
boolean |
是否平稳移动或立即移动 |
lookInDirectionOf
朝给定点方向看。
| 名称 | 类型 | 描述 |
|---|---|---|
x |
number |
点 x |
y |
number |
点 y |
z |
number |
点 z |
enableTransition |
boolean |
是否平稳移动或立即移动 |
setFocalOffset
使用屏幕平行坐标设置焦点偏移。
z与 Dolly 不同,它不会对正交摄影产生影响。
| 名称 | 类型 | 描述 |
|---|---|---|
x |
number |
水平偏移量 |
y |
number |
垂直偏移量 |
z |
number |
深度偏移量。结果与 Dolly 相同,但不受minDistance和的影响maxDistance |
enableTransition |
boolean |
是否平稳移动或立即移动 |
setOrbitPoint
不移动相机即可设置轨道点。
| 名称 | 类型 | 描述 |
|---|---|---|
targetX |
number |
轨道中心位置 x |
targetY |
number |
轨道中心位置 y |
targetZ |
number |
轨道中心位置 z |
forward
前进/后退。
| 名称 | 类型 | 描述 |
|---|---|---|
distance |
number |
向前/向后移动的量。负值表示向后移动 |
enableTransition |
boolean |
是否平稳移动或立即移动 |
moveTo
移动target位置到给定点。
| 名称 | 类型 | 描述 |
|---|---|---|
x |
number |
x 坐标移动中心位置 |
y |
number |
y 坐标移动中心位置 |
z |
number |
z 坐标移动中心位置 |
enableTransition |
boolean |
是否平稳移动或立即移动 |
elevate
向上/向下移动。
| 名称 | 类型 | 描述 |
|---|---|---|
height |
number |
向上/向下移动的量。负值表示向下移动 |
enableTransition |
boolean |
是否平稳移动或立即移动 |
fitToBox
使用最近的轴将视口适配到对象的框或边界框。填充以单位表示。
设置cover: true为填充输入屏幕。
| 名称 | 类型 | 描述 |
|---|---|---|
box3OrMesh |
THREE.Box3 |
THREE.Mesh |
enableTransition |
boolean |
是否平稳移动或立即移动 |
options |
object |
选项 |
options.cover |
boolean |
是否填充输入屏幕。默认为false |
options.paddingTop |
number |
顶部填充。默认为0 |
options.paddingRight |
number |
右填充。默认为0 |
options.paddingBottom |
number |
底部内边距。默认为0 |
options.paddingLeft |
number |
左填充。默认为0 |
fitToSphere
将视口与对象的球体或边界球体相适应。
| 名称 | 类型 | 描述 |
|---|---|---|
sphereOrMesh |
THREE.Sphere |
THREE.Mesh |
enableTransition |
boolean |
是否平稳移动或立即移动 |
fitToRect
将视口与矩形大小相适应。
| 名称 | 类型 | 描述 |
|---|---|---|
rect |
{width: number;height: number;center: [number, number, number],normal: [number, number, number]} |
矩形参数 |
setLookAt
target从来看position。
| 名称 | 类型 | 描述 |
|---|---|---|
positionX |
number |
相机位置 x。 |
positionY |
number |
相机位置 y。 |
positionZ |
number |
相机位置 z。 |
targetX |
number |
轨道中心位置 x。 |
targetY |
number |
轨道中心位置y。 |
targetZ |
number |
轨道中心位置 z。 |
enableTransition |
boolean |
是否平稳移动或立即移动 |
lerpLookAt
与 类似setLookAt,但它在两种状态之间进行插值。
| 名称 | 类型 | 描述 |
|---|---|---|
positionAX |
number |
观察的起始位置 x。 |
positionAY |
number |
观察的起始位置 y。 |
positionAZ |
number |
观察的起始位置 z。 |
targetAX |
number |
查看的起始位置 x。 |
targetAY |
number |
查看的起始位置 y。 |
targetAZ |
number |
查看的起始位置z。 |
positionBX |
number |
从位置 x 开始观察并进行插值。 |
positionBY |
number |
从位置 y 开始查看以进行插值。 |
positionBZ |
number |
从位置 z 开始观察并进行插值。 |
targetBX |
number |
查看要进行插值的位置 x。 |
targetBY |
number |
查看位置 y 进行插值。 |
targetBZ |
number |
查看要插入的位置 z。 |
t |
number |
0闭区间内的插值因子。该值必须是介于到之间的数字1,其中1为 100% |
enableTransition |
boolean |
是否平稳移动或立即移动 |
setPosition
根据给定位置设置角度和距离。
的别名setLookAt(),不改变目标。因此继续注视当前目标
| 名称 | 类型 | 描述 |
|---|---|---|
positionX |
number |
从 x 位置观察。 |
positionY |
number |
从 y 位置观察。 |
positionZ |
number |
从 z 位置观察。 |
enableTransition |
boolean |
是否平稳移动或立即移动 |
setTarget
设置注视的目标位置。
的别名setLookAt(),不改变位置。从而保持相同的位置。
| 名称 | 类型 | 描述 |
|---|---|---|
targetX |
number |
注视的位置 x。 |
targetY |
number |
查看的位置 y。 |
targetZ |
number |
注视的位置 z。 |
enableTransition |
boolean |
是否平稳移动或立即移动 |
setBoundary
设置包围相机目标的边界框box3。THREE.Box3
| 名称 | 类型 | 描述 |
|---|---|---|
box3 |
THREE.Box3? |
边界区域。没有删除边界的参数。 |
setViewport
设置(或取消设置)当前视口。
当您想要dollyToCursor同时使用渲染器视口和功能时,请设置此项。
参见:THREE.WebGLRenderer.setViewport()
| 名称 | 类型 | 描述 |
|---|---|---|
vector4 |
THREE.Vector4? |
代表视口的 Vector4,或者undefined用于取消设置它。 |
getTarget
返回相机所观察的轨道中心位置。
| 名称 | 类型 | 描述 |
|---|---|---|
out |
THREE.Vector3 |
接收 Vector3 实例来复制结果 |
receiveEndValue |
boolean |
是否接收转换结束坐标或当前坐标。默认为true |
getPosition
返回相机位置。
| 名称 | 类型 | 描述 |
|---|---|---|
out |
THREE.Vector3 |
接收 Vector3 实例来复制结果 |
receiveEndValue |
boolean |
是否接收转换结束坐标或当前坐标。默认为true |
getSpherical
返回轨道的球面坐标。
| 名称 | 类型 | 描述 |
|---|---|---|
out |
THREE.Vector3 |
接收 Spherical 实例复制结果 |
receiveEndValue |
boolean |
是否接收转换结束坐标或当前坐标。默认为true |
getFocalOffset
返回焦点偏移,即相机在屏幕平行坐标中平移的距离。
| 名称 | 类型 | 描述 |
|---|---|---|
out |
THREE.Vector3 |
接收 Vector3 实例来复制结果 |
receiveEndValue |
boolean |
是否接收转换结束坐标或当前坐标。默认为true |
saveState
将当前相机位置设置为默认位置。返回完整 CameraState 对象(字段:cameraPosition/cameraTarget/cameraZoom/cameraUp/cameraFocalOffset——vjmap3d@2.0.0)。
loadState
加载位置做为当前相机位置。
loadState(state, enableTransition?) 只要求 cameraPosition/cameraTarget(cameraUp 缺省 (0,1,0)、cameraZoom 缺省 1、cameraFocalOffset 缺省 0,自动补齐),值须为 THREE.Vector3(或含 x/y/z 的对象)。⚠️ 传数组 [x, y, z] 时内部读 .x 得 undefined → camera.position 变 NaN,相机坏掉且所有 Marker2D/Popup2D 的 CSS2D 元素随之消失(投影出 NaN → 渲染器判定不可见)。
normalizeRotations
将相机方位角旋转标准化为 0 至 360 度之间。
reset
将所有旋转和位置重置为默认值。
| 名称 | 类型 | 描述 |
|---|---|---|
enableTransition |
boolean |
是否平稳移动或立即移动 |
update
更新相机位置和方向。这应该在您的 tick 循环中调用,并true在需要重新渲染时返回。
| 名称 | 类型 | 描述 |
|---|---|---|
delta |
number |
上次更新调用之间的时间差 |
updateCameraUp
当您改变相机向上矢量时,运行.updateCameraUp()以同步。
applyCameraUp
将当前相机向上方向应用于相机。
轨道系统将使用当前位置重新初始化。
shake
相机抖动
| 名称 | 类型 | 描述 |
|---|---|---|
duration |
number |
每次持续时长 (ms) 默认 1000 |
frequency |
number |
抖动频率 默认 10 |
strength |
number |
强度 默认 1 |
isLoop |
number |
是否循环抖动 默认 false |
toJSON
获取 JSON 字符串中的所有状态
fromJSON
用 JSON 重现控制状态。enableTransition其中 anim 是否为布尔值。
高级
归一化累积方位角
如果您需要标准化的累积方位角(介于 0 到 360 度之间),请使用THREE.MathUtils.euclideanModulo
计算,例如:
const TAU = Math.PI * 2;
function normalizeAngle( angle ) {
return THREE.MathUtils.euclideanModulo( angle, TAU );
}
const normalizedAzimuthAngle = normalizeAngle( cameraControls.azimuthAngle );
找最短方位角旋转的绝对角度
您可能旋转了 380 度,但实际上您希望旋转 -20 度。
要获取绝对角度,请使用以下命令:
const TAU = Math.PI * 2;
function absoluteAngle( targetAngle, sourceAngle ){
const angle = targetAngle - sourceAngle
return THREE.MathUtils.euclideanModulo( angle + Math.PI, TAU ) - Math.PI;
}
console.log( absoluteAngle( 380 * THREE.MathUtils.DEG2RAD, 0 ) * THREE.MathUtils.RAD2DEG ); // -20deg
console.log( absoluteAngle( -1000 * THREE.MathUtils.DEG2RAD, 0 ) * THREE.MathUtils.RAD2DEG ); // 80deg
创建复杂的过渡
enableTransition所有接受参数返回Promise的方法均可用于创建复杂的动画,例如:
async function complexTransition() {
await cameraControls.rotateTo( Math.PI / 2, Math.PI / 4, true );
await cameraControls.dollyTo( 3, true );
await cameraControls.fitToSphere( mesh, true );
}
这将旋转相机,然后dolly,最后适应的边界球mesh。
.restThreshold可以使用和调整转换的速度和时间.smoothTime。
如果enableTransition是false,则立即返回:
// will resolve immediately
await cameraControls.dollyTo( 3, false );