持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第5天,点击查看活动详情
写在前面
本文用vue+threejs写物体动画:沿路径移动,沿着事先设定的路径移动物体。
通过鼠标点击控制是否移动。
下面是演示gif:
代码说明
- 大致说明
创建一个id容器,用于插入渲染器节点。
引入需要的threejs模块,这次引入了Flow,是实现沿路径移动的关键。
init方法中是主要的代码,下面会详细说明。
onPointerDown监听鼠标、手指按下事件,在鼠标按下的时候切换控制是否运动的值。
animate包含运动的代码,如果引入了Flow并且isFlow为true,则开始运动。
render是渲染的代码。
<template>
<div class="item">
<div id="THREE42"></div>
</div>
</template>
import * as THREE from "three";
import { Flow } from "three/examples/jsm/modifiers/CurveModifier.js";
mounted() {
this.initThreejs();
},
methods: {
initThreejs() {
let scene, camera, renderer, flow;
let isFlow = false; // 控制是否移动
init();
animate();
function init() { ... }
function onPointerDown(event) {
isFlow = !isFlow;
}
function animate() {
requestAnimationFrame(animate);
if (flow && isFlow) {
flow.moveAlongCurve(0.006);
}
render();
}
function render() {
renderer.render(scene, camera);
}
}
}
- 创建场景
scene = new THREE.Scene(); - 创建相机
创建一个透视相机PerspectiveCamera,并设置相机位置
camera = new THREE.PerspectiveCamera(
40,
(window.innerWidth - 201) / window.innerHeight,
1,
1000
);
camera.position.set(2, 2, 4); // 设置相机位置
camera.lookAt(scene.position);
- 创建灯光
创建一个平行光DirectionalLight和一个环境光AmbientLight,并且设置灯光的位置和光照的强度
const light = new THREE.DirectionalLight(0xffaa33); // 创建一个平行光
light.position.set(-10, 10, 10); // 设置灯光的位置
light.intensity = 1.0; // 设置光照的强度
scene.add(light); // 将灯光添加到场景中
const light2 = new THREE.AmbientLight(0x003973); // 创建一个环境光
light2.intensity = 1.0; // 设置光照的强度
scene.add(light2); // 将灯光添加到场景中
- 使用Catmull-Rom算法, 从一系列的点创建一条平滑的三维曲线
CatmullRomCurve3创建一个三维曲线,并将曲线闭合curve.closed = true;。通过LineLoop创建一条线,线的形状是三维曲线,线的材质是蓝色基础线条材质。
const curve = new THREE.CatmullRomCurve3([
new THREE.Vector3(1, 0, -1),
new THREE.Vector3(1, 0, 1),
new THREE.Vector3(-1, 0, 1),
new THREE.Vector3(-1, 0, -1),
]);
curve.curveType = "centripetal"; // 曲线的类型
curve.closed = true; // 曲线是否闭合
const points = curve.getPoints(50); // 获取点列表,50为要将曲线划分为的分段数
const line = new THREE.LineLoop(
new THREE.BufferGeometry().setFromPoints(points),
new THREE.LineBasicMaterial({ color: 0x0000ff })
); // 一条头尾相接的连续的线(参数说明:顶点列表,材质)
scene.add(line); // 将曲线添加到场景中
- 创建立方体,并且使用
Flow
创建一个红色基础网格材质的立方体,该立方体就是我们要移动的物体,通过flow.updateCurve(0, curve);确定要围绕的曲线
let redMesh = new THREE.Mesh(
new THREE.BoxGeometry(0.1, 0.1, 0.1),
new THREE.MeshBasicMaterial({ color: 0xff0000 })
); // 网格模型
flow = new Flow(redMesh); // 参数说明:(要克隆和修改以围绕曲线弯曲的网格模型)
flow.updateCurve(0, curve); // 参数说明:(索引,围绕的曲线)
scene.add(flow.object3D);
- 添加鼠标落下监听事件
document.addEventListener("pointerdown", onPointerDown); - 创建渲染器
创建渲染器并将渲染器插入到dom节点中
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setPixelRatio(window.devicePixelRatio); // 设置设备像素比
renderer.setSize(window.innerWidth - 201, window.innerHeight); // 考虑像素比重新调整画面大小
document.getElementById("THREE42").appendChild(renderer.domElement); // 将渲染器插入到html中
写在最后
以上就是所有的代码和说明,关键是Flow的使用方法。