Three.js渲染过程中如何调整动画运行速度
Three.js平面顶点动画平滑减速解决方案
你当前代码动画速度过快、过渡生硬的核心原因是每帧都为所有顶点生成全新的随机z值,没有过渡过程,视觉上呈现为快速闪烁跳变。setTimeout只会降低渲染帧率,不会改变z值跳变的逻辑,因此无法实现平滑放缓的效果。
下面提供两种可直接落地的实现方案:
方案一:插值过渡+定时更新目标值(易实现,可控性强)
实现逻辑
为每个顶点维护「当前z值」和「目标z值」两个变量,仅间隔固定时间更新一次目标值,每帧让当前z值缓慢向目标值靠拢,实现平滑过渡。
代码修改
- 初始化部分新增变量:
const geometry = new THREE.PlaneBufferGeometry(10, 10, 10, 10); const material = new THREE.MeshBasicMaterial( { side: THREE.DoubleSide, wireframe: true } ); const mesh = new THREE.Mesh( geometry, material ); const positions = geometry.attributes.position.array; scene.add(mesh); // ----- 以下为新增代码 ----- // 存储每个顶点的当前z值和目标z值 const vertexCount = geometry.attributes.position.count; const currentZ = new Array(vertexCount).fill(0); const targetZ = new Array(vertexCount).fill(0); // 平滑过渡速度:取值0~1,数值越小过渡越慢 const smoothSpeed = 0.02; // 目标值更新间隔:单位毫秒,数值越大整体动画节奏越慢 const updateInterval = 500; let lastUpdateTime = Date.now();
- 修改render函数的顶点更新逻辑:
function render() { mesh.rotateZ(0.001) const geoArray = geometry.attributes.position; const now = Date.now(); // 仅到间隔时间才更新所有顶点的目标z值 if (now - lastUpdateTime > updateInterval) { for (let i = 0; i < geoArray.count; i++) { targetZ[i] = Math.round(Math.random() * -2); } lastUpdateTime = now; } // 每帧让当前z值向目标z值线性插值 for (let i = 0; i < geoArray.count; i++) { currentZ[i] += (targetZ[i] - currentZ[i]) * smoothSpeed; geoArray.setZ(i, currentZ[i]); } mesh.geometry.attributes.position.needsUpdate = true; camera.updateProjectionMatrix() renderer.render(scene, camera) }
方案二:噪声函数驱动连续动画(效果更自然)
实现逻辑
用连续的Perlin/Simplex噪声函数,输入顶点索引和时间参数生成连续变化的z值,天然没有跳变,调整时间系数就能直接控制动画速度,视觉效果更自然流畅。
代码示例
// 动画速度系数,数值越小变化越慢 const noiseSpeed = 0.0005; function render() { mesh.rotateZ(0.001) const geoArray = geometry.attributes.position; const time = Date.now() * noiseSpeed; for (let i = 0; i < geoArray.count; i++) { // 用噪声生成连续z值,映射到你需要的-2~0范围 const noiseVal = THREE.MathUtils.smoothstep(THREE.MathUtils.randFloat(-1, 1), -1, 1); // 也可以替换为你引入的Perlin/Simplex噪声函数,效果更好 const z = (noiseVal * 0.5 - 0.5) * 2; geoArray.setZ(i, Math.round(z)); } mesh.geometry.attributes.position.needsUpdate = true; camera.updateProjectionMatrix() renderer.render(scene, camera) }
内容的提问来源于stack exchange,提问作者Tarjay
相关产品推荐
相关产品推荐

