本章简单介绍threejs的基本用法。从最基础的代码写起,去了解threejs的大致使用流程。threejs中主要包含:场景,相机,渲染器,以及要展示的相关物体。
本文主要总结了B站老陈打码的three.js入门课程基本知识点,具体内容可去视频网站查看。
1、引入threejs包
首先先下载相关的npm包。
npm i --save three
然后通过import引入所需要的构造函数等
import { Scene, PerspectiveCamera, WebGLRenderer, BoxGeometry, MeshBasicMaterial, Mesh, AxesHelper } from 'three';
2、搭建基本的代码
// 场景
const scene = new Scene();
// 相机
const camera = new PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(0, 0, 10);
scene.add(camera);
// 相关物体
const geometry = new BoxGeometry(1, 1, 1);
const material = new MeshBasicMaterial({ color: 0x00ff00 });
const cube = new Mesh(geometry, material);
scene.add(cube);
// 渲染器
const renderer = new WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
renderer.render(scene, camera);
以上通过搭建一个场景,在场景中加入相机,物体,然后通过渲染器把画面渲染到dom元素中。上面的renderer.domElement其实是一个canvas元素。
代码效果:
3、加入轨道控制器和坐标辅助器
// 导入轨道控制器
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
// 创建轨道控制器
const controls = new OrbitControls(camera, renderer.domElement);
// 设置控制器阻尼,让控制器更有真实效果,必须在动画循环里调用.update()。
controls.enableDamping = true;
// 添加坐标轴辅助器
const axesHelper = new AxesHelper(5);
scene.add(axesHelper);
// 动画函数
function animate() {
controls.update();
renderer.render(scene, camera);
requestAnimationFrame(animate);
}
animate();
轨道控制器可以使得相机围绕目标进行轨道运动,其引入方式和其他的引入不太一样,需要从examples引入。引入后,鼠标即可拖拽物体进行多方位查看。轨道控制器创建成功后,需要启动动画函数才会生效。控制的阻尼效果,是停止对物体的拖拽查看后,物体会慢慢停下,而不是立刻。
下图中的红,绿,蓝三条线即为添加的坐标轴,分别对应x,y,z轴。为了区分颜色,给正方体换成了黄色。
4、加入物体移动,旋转动画
function animate() {
cube.position.x += 0.01;
if (cube.position.x > 5) {
cube.position.x = 0;
}
cube.rotation.x += Math.PI / 180;
renderer.render(scene, camera);
requestAnimationFrame(animate);
}
通过在动画函数中修改正方体的位置属性,从而实现最基础的物体移动。效果如下:
不过,这种移动可能会出现忽快忽慢的情况。本质原因是requestAnimationFrame会在每一帧之前进行回调,但实际情况中,帧间隔时间不是稳定的。代码进行优化如下:
function animate(time: DOMHighResTimeStamp) {
let t = (time / 1000) % 5;
cube.position.x = t * 1;
renderer.render(scene, camera);
requestAnimationFrame(animate);
}
以上写法是通过我们自己去修改物体的属性来完成平移和旋转。接下来是借助一个工具库gsap,完成同样的动画。首先安装:
npm i gsap
下面是新代码:
// 设置动画
let animate1 = gsap.to(cube.position, {
x: 5,
duration: 5,
ease: "power1.inOut",
// 设置重复的次数,无限次循环-1
repeat: -1,
// 往返运动
yoyo: true,
// delay,延迟2秒运动
delay: 2,
onComplete: () => {
console.log("动画完成");
},
onStart: () => {
console.log("动画开始");
},
});
// 动画函数
function animate(time: DOMHighResTimeStamp) {
renderer.render(scene, camera);
requestAnimationFrame(animate);
}
通过gsap设置对应的动画,相关属性介绍都在代码中,具体的用法可前往官网查看。通过事件,我们也可以实现动画的暂停和继续。如下:
window.addEventListener("dblclick", () => {
if (animate1.isActive()) {
// 暂停
animate1.pause();
} else {
// 恢复
animate1.resume();
}
});
5、画面自适应优化
当窗口大小变化时,需要更新摄像头和渲染器来保证良好的视觉效果。如下:
// 监听画面变化,更新渲染画面
window.addEventListener("resize", () => {
// 更新摄像头
camera.aspect = window.innerWidth / window.innerHeight;
// 更新摄像机的投影矩阵
camera.updateProjectionMatrix();
// 更新渲染器
renderer.setSize(window.innerWidth, window.innerHeight);
// 设置渲染器的像素比
renderer.setPixelRatio(window.devicePixelRatio);
});
6、添加可视化页面GUI
可视化GUI用于用户手动控制场景的物体等。通过GUI可以随时调节物体的位置,颜色,是否展示,动画等等。
// 修改物体位置
gui
.add(cube.position, "x")
.min(0)
.max(5)
.step(0.01)
.name("移动x轴")
.onChange((value) => {
console.log("值被修改:", value);
})
.onFinishChange((value) => {
console.log("完全停下来:", value);
});
// 修改物体的颜色
const params = {
color: "#ffff00",
fn: () => {
// 让立方体运动起来
gsap.to(cube.position, { x: 5, duration: 2, yoyo: true, repeat: -1 });
},
};
gui.addColor(params, "color").onChange((value) => {
cube.material.color.set(value);
});
// 设置选项框
gui.add(cube, "visible").name("是否显示");
var folder = gui.addFolder("设置立方体");
folder.add(cube.material, "wireframe");
// 设置按钮点击触发某个事件
folder.add(params, "fn").name("立方体运动");
如下图所示,滑动移动X轴,可以更改物体在x轴的位置;点击color可以修改物体的颜色......