news 2026/4/14 17:03:53

学习: Threejs进阶 (1)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
学习: Threejs进阶 (1)

一、坐标系与三角函数

沿着圆弧批量创建多个小球

import * as THREE from "three"; const R = 100; //圆弧半径 const N = 10; //分段数量 const sp = Math.PI / N; //两个相邻点间隔弧度 const group = new THREE.Group(); for (let i = 0; i < N + 1; i++) { const angle = sp * i; // 以坐标原点为中心,在XOY平面上生成圆弧上的顶点数据 const x = R * Math.cos(angle); const y = R * Math.sin(angle); const geometry = new THREE.SphereGeometry(3); const material = new THREE.MeshLambertMaterial({ color: 0x00ffff }); const mesh = new THREE.Mesh(geometry, material); mesh.position.set(x, y, 0); group.add(mesh); } export default group;

二、 三维向量Vector3简介

Vector3表示位移量(向量)

const A = new THREE.Vector3(30, 30, 0);// 人起点A // walk表示运动的位移量用向量 const walk = new THREE.Vector3(100, 50, 0); const B = new THREE.Vector3();// 人运动结束点B // 计算结束点xyz坐标 B.x = A.x + walk.x; B.y = A.y + walk.y; B.z = A.z + walk.z; console.log('B',B);

向量加法运算.addVectors()

const A = new THREE.Vector3(30, 30, 0); // 人起点A // walk表示运动的位移量用向量 const walk = new THREE.Vector3(100, 50, 0); const B = new THREE.Vector3(); // 人运动结束点B // addVectors的含义就是参数中两个向量xyz三个分量分别相加 B.addVectors(A, walk); console.log("B", B);

向量复制方法.copy()

// 两个小球网格模型可视化A点和B点 mesh1.position.copy(A); mesh2.position.copy(B);

向量加法运算.add()

A.add(walk);

如果不希望A被改变,且创建一个新的对象表示B点坐标,通过克隆方法.clone()

// A.clone()克隆一个和A一样对象,然后再加上walk,作为B // A不执行.clone(),A和B本质上都指向同一个对象 const B = A.clone().add(walk);

Vector3表示速度(向量)

// 向量v表示人速度,大小√2米每秒,方向是x、y正半轴的角平分线 const v = new THREE.Vector3(1, 1, 0); // xyz三个方向上速度分别和时间相乘,得到三个方向上位移 const walk = new THREE.Vector3(v.x * 50, v.y * 50, v.z * 50); // 运动50秒结束位置B const B = A.clone().add(walk); console.log("B", B);

向量方法.multiplyScalar()

// `.multiplyScalar(50)`表示向量x、y、z三个分量和参数分别相乘 const walk = v.clone().multiplyScalar(50); // xyz三个方向上速度分别和时间相乘,得到三个方向上位移 // const walk = new THREE.Vector3(v.x * 50, v.y * 50, v.z * 50);

三、向量大小(Vector3长度.length())

计算AB两点之间距离

const A = new THREE.Vector3(30, 30, 0); // 人起点A const B = new THREE.Vector3(130, 80, 0); // 人运动结束点B // 3D空间,A和B两点之间的距离 const L = Math.sqrt( Math.pow(B.x - A.x, 2) + Math.pow(B.y - A.y, 2) + Math.pow(B.z - A.z, 2) ); console.log("B", B); console.log("A", A); console.log("L", L);

向量Vector3表示位移量

const A = new THREE.Vector3(30, 30, 0); const B = new THREE.Vector3(130, 80, 0); const AB = new THREE.Vector3(); AB.x = B.x - A.x; AB.y = B.y - A.y; AB.z = B.z - A.z; console.log("AB", AB);

向量减法运算.subVectors()

AB.subVectors(B, A);

向量减法运算.sub()

B.sub(A); console.log('B',B);

const AB = B.clone().sub(A);

向量长度.length()

向量长度.length()的内部代码,本质上就是x、y、z三个分量平方和的平方根

const L = AB.length(); console.log("L", L);

速度向量长度.length()

v表示速度向量,v的长度.length()是就是速度的大小

const v = new THREE.Vector3(1, 1, 0); const vL = v.length(); console.log("vL", vL);

四、向量方向(归一化.normalize)

单位向量

单位向量是向量长度.length()为1的向量。

向量归一化.normalize()

向量归一化,就是等比例缩放向量的xyz三个分量,缩放到向量长度.length()为1。

// 单位向量v const v = new THREE.Vector3(1, 0, 0); console.log("向量长度", v.length()); // 非单位向量dir const dir = new THREE.Vector3(1, 1, 0); dir.normalize(); //向量归一化 //Vector3(√2/2, √2/2, 0) Vector3(0.707, 0.707, 0) console.log("dir", dir);

import * as THREE from "three"; const group = new THREE.Group(); const geometry = new THREE.SphereGeometry(3); const material = new THREE.MeshLambertMaterial({ color: 0x00ffff }); const mesh1 = new THREE.Mesh(geometry, material); const A = new THREE.Vector3(30, 30, 0); mesh1.position.copy(A); group.add(mesh1); export default group;

物体沿着直线AB平移:单位向量表示平移方向

//直线上两点坐标A和B const A = new THREE.Vector3(30, 30, 0); const B = new THREE.Vector3(100,0,100); const AB = B.clone().sub(A);//AB向量 AB.normalize();//AB归一化表示直线AB的方向 console.log("AB", AB);

用向量表示平移过程

const T = AB.clone().multiplyScalar(100); console.log("T", T); console.log("向量T长度", T.length());

向量加法.add()平移网格模型Mesh

mesh1.position.add(T);

平移方法.translateOnAxis()

//沿着AB方向平移100 mesh1.translateOnAxis(AB, 100);

五、相机沿着视线方向运动

单位向量表示相机视线方向

实例化三维向量

// 相机目标观察点和相机位置相减,获得一个沿着相机视线方向的向量 const dir = new THREE.Vector3(0 - 202,0 - 123,0 - 125); // 归一化,获取一个表示相机视线方向的单位向量。 dir.normalize(); console.log("相机方向", dir); console.log("单位向量", dir.length());

camera.getWorldDirection()获取相机视线方向

const dir = new THREE.Vector3(); // 获取相机的视线方向 camera.getWorldDirection(dir); console.log('相机方向',dir); console.log('单位向量',dir.length());

相机沿着视线方向平移

// dis向量表示相机沿着相机视线方向平移200的位移量 const dis = dir.clone().multiplyScalar(50); // 相机沿着视线方向平移 camera.position.add(dis);

相机沿着视线移动动画(tweenjs库辅助)

// 创建一个 Group 来管理所有 tweens const tweenGroup = new Group(); // 相机动画:平移前坐标——>平移后坐标 const tween = new Tween(camera.position) .to(camera.position.clone().add(dis), 3000) .start(); // 将 tween 添加到组中 tweenGroup.add(tween);
// 渲染循环 function render() { tweenGroup.update(); // 使用 Group 更新动画 composer.render(); renderer.render(scene, camera); requestAnimationFrame(render); } render();

GUI沿着相机视线方向拖动相机平移

// 从threejs扩展库引入gui.js import { GUI } from "three/addons/libs/lil-gui.module.min.js";
// 将 tween 添加到组中 // tweenGroup.add(tween); const pos0 = camera.position.clone(); //记录相机初始位置 const gui = new GUI(); // L:相机沿着视线移动距离,从0~50 gui.add({ L: 0 }, "L", 0, 50).onChange(function (v) { const dis = dir.clone().multiplyScalar(v); //相机沿着视线偏移长度v const newPos = pos0.clone().add(dis); //相机初始位置+相机偏移向量 camera.position.copy(newPos); //新的位置赋值给相机位置 });

六、箭头ArrowHelper

import * as THREE from "three"; const group = new THREE.Group(); const A = new THREE.Vector3(0, 30, 0); //A点 const B = new THREE.Vector3(80, 0, 0); //B点 // 绿色小球可视化A点位置 const AMesh = createSphereMesh(0x00ff00, 2); AMesh.position.copy(A); // 红色小球可视化B点位置 const BMesh = createSphereMesh(0xff0000, 2); BMesh.position.copy(B); function createSphereMesh(color, R) { const geometry = new THREE.SphereGeometry(R); const material = new THREE.MeshLambertMaterial({ color: color, }); const mesh = new THREE.Mesh(geometry, material); return mesh; } group.add(AMesh, BMesh); export default group;

// 绘制一个从A指向B的箭头 const AB = B.clone().sub(A); const L = AB.length(); //AB长度 const dir = AB.clone().normalize(); //单位向量表示AB方向 // 生成箭头从A指向B const arrowHelper = new THREE.ArrowHelper(dir, A, L); group.add(arrowHelper);

箭头可视化一个立方体的法线方向

const geometry = new THREE.BoxGeometry(50, 50, 50); const material = new THREE.MeshLambertMaterial({ color: 0x00ffff, }); const mesh = new THREE.Mesh(geometry, material); const p = mesh.geometry.attributes.position; const n = mesh.geometry.attributes.normal; const count = p.count; //顶点数量 for (let i = 0; i < count; i++) { // 顶点位置O const O = new THREE.Vector3(p.getX(i), p.getY(i), p.getZ(i)); // 顶点位置O对应的顶点法线 const dir = new THREE.Vector3(n.getX(i), n.getY(i), n.getZ(i)); // 箭头可视化顶点法线 const arrowHelper = new THREE.ArrowHelper(dir, O, 20); mesh.add(arrowHelper); } group.add(mesh);

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/11 12:12:45

AI驱动交易革新:3个突破性功能重新定义散户量化工具

AI驱动交易革新&#xff1a;3个突破性功能重新定义散户量化工具 【免费下载链接】tradingview-assistant-chrome-extension An assistant for backtesting trading strategies and checking (showing) external signals in Tradingview implemented as a Chrome browser extens…

作者头像 李华
网站建设 2026/4/13 11:05:44

AutoCAD字体管理革命性突破:3分钟解决80%设计师的字体难题

AutoCAD字体管理革命性突破&#xff1a;3分钟解决80%设计师的字体难题 【免费下载链接】FontCenter AutoCAD自动管理字体插件 项目地址: https://gitcode.com/gh_mirrors/fo/FontCenter 您是否曾因AutoCAD字体缺失导致图纸文字显示异常&#xff1f;FontCenter作为一款免…

作者头像 李华
网站建设 2026/4/13 6:19:34

革新性歌词增强工具:3大突破告别传统播放器歌词显示困扰

革新性歌词增强工具&#xff1a;3大突破告别传统播放器歌词显示困扰 【免费下载链接】ESLyric-LyricsSource Advanced lyrics source for ESLyric in foobar2000 项目地址: https://gitcode.com/gh_mirrors/es/ESLyric-LyricsSource 为什么传统歌词显示总是差强人意&…

作者头像 李华