THREE JS PointLight实现类似FastLED、WLED的平滑颜色插值动画
实现WLED风格平滑调色板过渡的解决方案
问题根因
你之前直接定时切换颜色的逻辑没有为颜色过渡留足时间轴,使用Color.lerp()没有得到理想效果大概率是因为没有逐帧计算过渡进度,仅在颜色切换的瞬间执行了单次插值。
具体实现步骤
1. 先补充定义必要的状态变量
在animate函数外部声明以下变量:
// 原有变量保留:then, nextTime, party等 const colorTransitionDuration = 0.8; // 单段颜色过渡总时长,单位秒,可自行调整 let currentColorIndex = 0; // 当前所在的调色板颜色索引 let transitionStartTime = 0; // 当前过渡段的起始时间 let startColor = new THREE.Color(party[0]); // 过渡起始颜色 let targetColor = new THREE.Color(party[1]); // 过渡目标颜色
2. 替换原有颜色切换逻辑
修改animate函数中处理颜色的部分:
function animate(now) { now *= 0.001; var deltaTime = now - then; then = now; if (resizeRendererToDisplaySize(renderer)) { const canvas = renderer.domElement; camera.aspect = canvas.clientWidth / canvas.clientHeight; camera.updateProjectionMatrix(); } // 计算当前过渡段的进度,范围0-1 let transitionProgress = (now - transitionStartTime) / colorTransitionDuration; transitionProgress = Math.max(0, Math.min(1, transitionProgress)); // 限制在合法范围 // 进度到1的时候切换到下一段过渡 if (transitionProgress >= 1) { currentColorIndex = (currentColorIndex + 1) % party.length; const nextColorIndex = (currentColorIndex + 1) % party.length; startColor = new THREE.Color(party[currentColorIndex]); targetColor = new THREE.Color(party[nextColorIndex]); transitionStartTime = now; transitionProgress = 0; } // 逐帧计算插值后的颜色 const currentColor = startColor.clone().lerp(targetColor, transitionProgress); // 更新所有pl点光源的颜色 scene.children.forEach(function (e) { if (e.name.includes("pl")) { // 如果需要保留原有的灯珠相位差效果,给每个灯加单独的进度偏移即可 // 示例:let ledOffset = (currentLed / numPixels) % 1; // let ledProgress = (transitionProgress + ledOffset) % 1; // let ledColor = startColor.clone().lerp(targetColor, ledProgress); e.color.copy(currentColor); // 辅助球同步颜色 //e.children[0].material.color.copy(currentColor); } }); // 原有其他逻辑保留:controls更新、stats更新、渲染等 controls.update(); stats.update(); requestAnimationFrame(animate); renderer.render(scene, camera); }
效果调整说明
- 修改
colorTransitionDuration的数值可以调整颜色过渡的快慢,数值越小切换越快 - 如果需要还原WLED跑马灯式的逐灯偏移效果,打开注释里的灯珠偏移逻辑即可,每个灯珠的过渡进度会错开,形成流动效果
- 如需更接近WLED的gamma校正效果,可以在插值后对颜色做gamma 2.2校正,适配人眼对亮度的感知:
currentColor.convertSRGBToLinear()
内容的提问来源于stack exchange,提问作者it.Carl
相关产品推荐
相关产品推荐

