Appearance
相机基础
正投影相机
js
// 正投影相机
OrthographicCamera(left, right, top, bottom, near, far);
参数 | 含义 |
---|---|
left, right, top, bottom | 渲染左右上下边界 |
near | 距离相机开始渲染的位置,默认 0.1 |
far | 距离相机截止渲染的位置, 默认 2000 |
创建正投影相机
设置渲染范围
js// 正投影相机 const width = window.innerWidth; //canvas画布宽度 const height = window.innerHeight; //canvas画布高度 const k = width / height; //canvas画布宽高比 const s = 600; //控制left, right, top, bottom范围大小 const camera = new THREE.OrthographicCamera(-s * k, s * k, s, -s, 1, 8000);
相机位置和观察目标
jscamera.position.set(0, 2000, 0); //相机放在y轴上 camera.lookAt(0, 0, 0); //指向坐标原点
更新 canvas 画布尺寸
js
// Canvas画布跟随窗口变化
window.onresize = function () {
const width = window.innerWidth; //canvas画布宽度
const height = window.innerHeight; //canvas画布高度
// 1. WebGL渲染器渲染的Cnavas画布尺寸更新
renderer.setSize(width, height);
// 2.1.更新相机参数
const k = width / height; //canvas画布宽高比
camera.left = -s * k;
camera.right = s * k;
// 2.2.相机的left, right, top, bottom属性变化了,通知threejs系统
camera.updateProjectionMatrix();
};
包围盒
把模型的所有顶点数据包围在一个最小的长方体空间中,这个最小长方体空间就是该模型的包围盒 Box3
使用 min 和 max 两个属性来描述包围区域, 属性值都是三维向量对象 Vector3
计算模型最小包围盒.expandByObject()
可以查看模型的包围盒属性.min
和.max
。
js
const box3 = new THREE.Box3();
box3.expandByObject(mesh); // 计算模型包围盒
console.log("查看包围盒", box3);
包围盒尺寸.getSize()
可以获取包围盒的长宽高
js
const scale = new THREE.Vector3();
// getSize()计算包围盒尺寸
// 获得包围盒长宽高尺寸,结果保存在参数三维向量对象scale中
box3.getSize(scale);
console.log("模型包围盒尺寸", scale);
包围盒几何中心.getCenter()
js
// 计算包围盒中心坐标
const center = new THREE.Vector3();
box3.getCenter(center);
console.log("模型中心坐标", center);
相机动画
通过改变相机对象 Camera
的.position
属性和.lookAt()
方法,实现一段相机动画
直线运动
js
// 渲染循环
function render() {
camera.position.z -= 0.3; //相机直线运动动画
renderer.render(scene, camera);
requestAnimationFrame(render);
}
render();
圆周运动
js
// 渲染循环
let angle = 0; //用于圆周运动计算的角度值
const R = 100; //相机圆周运动的半径
function render() {
angle += 0.01;
// 相机y坐标不变,在XOZ平面上做圆周运动
camera.position.x = R * Math.cos(angle);
camera.position.z = R * Math.sin(angle);
renderer.render(scene, camera);
requestAnimationFrame(render);
}
render();
执行lookAt()
计算相机视线方向
改变.position
属性后,如果不执行.lookAt()
方法,相机的观察方向默认不变
js
function render() {
angle += 0.01;
camera.position.x = R * Math.cos(angle);
camera.position.z = R * Math.sin(angle);
// .position改变,重新执行lookAt(0,0,0)计算相机视线方向
camera.lookAt(0, 0, 0);
requestAnimationFrame(render);
}
render();
旋转渲染结果
指定相机的方向属性.up
, 使一个坐标轴方向朝上
js
// 你可以看到模型相比原来上下颠倒 y坐标轴朝下
camera.up.set(0, -1, 0);
//渲染效果:红色x轴向上
camera.up.set(1, 0, 0);
//渲染效果:蓝色z轴向上
camera.up.set(0, 0, 1);
执行顺序
.up
属性和.position
属性,如果在.lookAt()
执行之后改变,需要重新执行.lookAt()
js
camera.lookAt(0, 0, 0);
camera.up.set(0, 0, 1); //改变up
camera.lookAt(0, 0, 0); //执行lookAt重新计算相机姿态
旋转缩放限制OrbitControls
限制属性
禁止右键平移
.enablePan
jscontrols.enablePan = false;
禁止缩放
.enableZoom
jscontrols.enableZoom = false;
禁止旋转
.enableRotate
jscontrols.enableRotate = false;
OrbitControls.target
属性
- 对应的相机的
.lookAt()
观察目标 - 执行
controls.update();
, 相机控件内部会执行camera.lookAt(controls.target)
js
// controls.target默认值是坐标原点
controls.target.set(x, y, z);
//update()函数内会执行camera.lookAt(x, y, z)
controls.update();
透视投影缩放范围
OrbitControls
缩放,本质上就是改变相机的位置属性.position
- 通过设置
.minDistance
和.maxDistance
, 约束相机位置.position
的变化范围, 控制缩放范围
js
//相机位置与观察目标点最小值
controls.minDistance = 200;
//相机位置与观察目标点最大值
controls.maxDistance = 500;
正投影缩放范围
正投影的缩放范围, 通过相机控件OrbitControls
的.minZoom
和.maxZoom
属性实现
js
// 缩放范围
controls.minZoom = 0.5;
controls.maxZoom = 2;
获取相机与目标观察点的距离.getDistance()
js
//相机位置与目标观察点距离
const dis = controls.getDistance();
console.log("dis", dis);
可视化设置相机缩放范围
实时打印相机与目标距离, 得到理想的minDistance
和maxDistance
js
controls.addEventListener("change", function () {
//相机位置与目标观察点距离
const dis = controls.getDistance();
console.log("dis", dis);
});
设置旋转范围
通过
.minPolarAngle
和.maxPolarAngle
属性控制上下的旋转范围- 默认情况下 0 度,XOZ 平面平行 canvas 画布,y 轴垂直指向屏幕外
- 90 度时候,渲染结果 y 轴竖直向上
- 180 度,XOZ 平面平行 canvas 画布,y 轴垂直指向屏幕内
js
// 上下旋转范围
controls.minPolarAngle = 0; //默认值0
controls.maxPolarAngle = Math.PI; //默认值Math.PI
.maxPolarAngle
属性设置为 90 度,这样不能看到模型底部:
js
controls.maxPolarAngle = Math.PI / 2;
- 通过
.minAzimuthAngle
和.maxAzimuthAngle
属性控制左右的旋转范围。
js
// 左右旋转范围
controls.minAzimuthAngle = -Math.PI / 2;
controls.maxAzimuthAngle = Math.PI / 2;
相机控件MapControls
好像和OrbitControls
功能差不多, 除了鼠标执行事件有所不同
引入
js
// 引入相机控件`MapControls`
import { MapControls } from "three/addons/controls/OrbitControls.js";
const controls = new MapControls(camera, renderer.domElement);
使用
同上OrbitControls