Three.js的3D模型旋转时为什么会卡顿?
最近在用Three.js做3D图表时遇到个问题,当给模型添加自旋动画后,页面滚动就变得卡顿了。模型本身也不算太大,是用glTF加载的,旋转代码也按官方示例写的:
function animate() {
requestAnimationFrame(animate);
mesh.rotation.x += 0.01;
mesh.rotation.y += 0.01;
renderer.render(scene, camera);
}
试过把动画改成用CSS,但模型位置就对不准了。也尝试过用THREE.LoopEuler参数,但好像没什么变化。难道是渲染设置哪里没配好?
首先你得做帧率节流和可见性检测。别直接无脑 requestAnimationFrame 嵌套调用。加个时间判断,比如控制旋转更新频率:
其次要做页面可见性校验。用户切到别的标签页时,动画完全没必要跑。加个监听页面可见性的钩子:
另外检查下你的 glTF 模型有没有做纹理压缩和几何体简化。可以用 THREE.DRACOLoader 解压 Draco 压缩的网格,加载时显式启用:
gltfLoader.setDRACOLoader(dracoLoader)还有,确认 renderer 开启了抗锯齿和自动清除缓存:
最后提醒一点,别在主线程干太多事。如果图表数据量大,考虑把旋转逻辑拆到 Web Worker 或者用 CSS 3D 层级叠加(但要注意 z-index 和 transform-origin 对齐)。不过 Three.js 本身不推荐全丢给 CSS,容易失控。
先加上时间间隔控制和 visibility 校验,90% 的卡顿都能缓解。
requestAnimationFrame中直接修改了模型的旋转值,这种做法会破坏 Three.js 的渲染调度,导致每一帧都强制重绘。官方推荐的做法是通过Clock类来管理动画时间,而不是用累加的方式。你应该改成这样:
这样可以让旋转速度与帧率解耦,避免因帧率波动导致动画卡顿。
另外,如果你的模型是静态的,只有旋转动画,建议开启
renderer.autoClear = false并手动控制渲染频率,或者使用OrbitControls自带的自动更新机制。如果你不需要每帧都渲染,可以限制animate()的调用频率。最后检查一下你的 glTF 是否带了大量骨骼或动画,这些也会影响性能。用
GLTFLoader加载时记得启用draco压缩(如果用了),能有效降低模型资源占用。