经纬志
首页 / three.js / API 文档

Vector3

先看结论

三维向量,同时用作点的坐标、方向与法线,是场景里出现频率最高的数据类型。

最后验证 2026-11-03 · three.js 0.160.0 · 更新 2026-10-28 · 引用本文
new THREE.Vector3(x, y, z) → Vector3

构造参数

参数默认说明
x0横向分量
y0纵向分量,three.js 默认 Y 轴朝上
z0前后分量,朝向观察者一侧为正

属性

属性说明
x / y / z三个分量,可直接读写
isVector3只读标记,用于类型判断

常用方法

方法说明
set(x, y, z)就地赋值,返回自身,可链式调用
copy(v) / clone()前者就地复制,后者返回新对象
add(v) / addVectors(a, b)相加;带 Vectors 后缀的版本不消耗中间对象
sub(v) / subVectors(a, b)相减,常用于求两点间的方向
multiplyScalar(s)按标量缩放
dot(v) / cross(v)点积与叉积,叉积会就地改写自身
length() / lengthSq() / normalize()模长、模长平方、单位化
distanceTo(v) / distanceToSquared(v)两点距离;只做比较时用平方版本省一次开方
lerp(v, t) / lerpVectors(a, b, t)线性插值,t 取 0 到 1
applyMatrix4(m)乘 4×4 矩阵,含平移
applyQuaternion(q) / applyAxisAngle(axis, angle)按四元数或绕轴旋转
project(camera) / unproject(camera)世界坐标与裁剪空间坐标互转,结果为归一化设备坐标
setFromMatrixPosition(m)取矩阵的平移分量
setFromSphericalCoords(r, phi, theta)球坐标转直角坐标,phi 从 +Y 轴起算,theta 绕 Y 轴
fromArray(arr, offset) / toArray(arr, offset)与 Float32Array 互转,写几何体属性时使用
equals(v)逐分量比较,浮点误差不会自动容差

基本用法

const a = new THREE.Vector3(1, 2, 3);
const b = new THREE.Vector3(4, 0, -2);

// 中点
const mid = new THREE.Vector3().addVectors(a, b).multiplyScalar(0.5);

// 方位与距离
const offset = new THREE.Vector3().subVectors(b, a);
const dist = offset.length();
const dir = offset.normalize();   // 注意:normalize 会改写 offset

mesh.position.copy(mid);
mesh.lookAt(b);

normalize()、add()、cross() 都直接改写自身并返回自身, 这是 three.js 一贯的风格。需要保留原值的场合,先 clone()。

经纬度转球面坐标

经纬度是角度,场景坐标是直角坐标,两者之间需要一次换算。 球面近似下,把经度当绕 Y 轴的方位角、纬度当从赤道起算的高度角即可:

const R = 6371000;   // 地球平均半径,单位米

function lonLatToVector3(lon, lat, radius) {
  const phi = THREE.MathUtils.degToRad(90 - lat);
  const theta = THREE.MathUtils.degToRad(lon);

  return new THREE.Vector3(
    radius * Math.sin(phi) * Math.cos(theta),
    radius * Math.cos(phi),
    radius * Math.sin(phi) * Math.sin(theta)
  );
}

const beijing = lonLatToVector3(116.39, 39.9, 1);

这段换算只解决了球面上的位置,不涉及投影带、基准面与椭球改正。 three.js 没有地理坐标系统,坐标系的原点、轴向与单位都由使用者自己定义, 并在整个项目里保持一致。

投影与拾取

// 世界坐标 → 屏幕坐标(结果 x、y 在 -1 到 1,z 为深度)
const ndc = new THREE.Vector3(12, 0, 8).project(camera);
const px = (ndc.x * 0.5 + 0.5) * canvas.clientWidth;

// 屏幕坐标 → 世界坐标:给一个 NDC 深度再反投影
const world = new THREE.Vector3(ndc.x, ndc.y, ndc.z).unproject(camera);

project 依赖相机的投影矩阵与世界矩阵,调用前要确保相机矩阵已更新, 通常在渲染之后或 camera.updateMatrixWorld() 之后取用。

单位自己定,three.js 不管。把 1 个单位当成米、十米还是一度都可以, 但一旦确定就不能混用。半径 6371000 的地球与 100 米见方的建筑放在同一场景里, 浮点精度会明显不足。

引用本文

经纬志(2026)。《Vector3》。https://www.jingweizhi.com/three/api/vector3.html(访问日期 2026-11-03)。