Three.js搭建小米SU7三维汽车实战(6)颜色切换
颜色切换
接下来我们来实现懂车帝的颜色切换效果
可以让ai帮我们生成页面结构以及样式,注意changeCarBodyColor这个函数需要我们自己来写
// 创建颜色选择器UI
function createColorSelector() {const colors = [{ name: "深海蓝", hex: "#1A9CB0" },{ name: "玛瑙红", hex: "#A00039" },{ name: "橄榄绿", hex: "#6E7555" },{ name: "雅灰", hex: "#D6D7D9" },{ name: "紫檀", hex: "#614C63" }];const container = document.createElement("div");container.className = "color-selector";colors.forEach((color, index) => {const colorBtn = document.createElement("div");colorBtn.className = "color-btn";colorBtn.setAttribute("data-color", color.hex);colorBtn.style.backgroundColor = color.hex;// 默认选中第一个if (index === 0) {colorBtn.classList.add('active');}// 颜色名称标签const colorLabel = document.createElement("div");colorLabel.className = "color-label";colorLabel.textContent = color.name;colorBtn.appendChild(colorLabel);container.appendChild(colorBtn);});// 使用事件委托添加点击事件container.addEventListener('click', function(event) {// 查找被点击的按钮元素let targetBtn = event.target;// 如果点击的是标签元素,则获取其父元素(按钮)if (targetBtn.classList.contains('color-label')) {targetBtn = targetBtn.parentElement;}// 确认点击的是按钮元素if (targetBtn.classList.contains('color-btn')) {// 移除所有按钮的active类document.querySelectorAll('.color-btn').forEach(btn => {btn.classList.remove('active');});// 为当前按钮添加active类targetBtn.classList.add('active');// 获取颜色值,用于外部实现的功能const colorValue = targetBtn.getAttribute('data-color');console.log('选中颜色:', colorValue);// 这里不实现具体功能,由用户自行实现changeCarBodyColor(colorValue)}});document.body.appendChild(container);
}
/* 颜色选择器样式 */
.color-selector {position: fixed;bottom: 60px;left: 50%;transform: translateX(-50%);display: flex;gap: 20px;align-items: center;justify-content: center;width: 100%;max-width: 500px;padding: 0 10px;box-sizing: border-box;
}.color-btn {width: 30px;height: 30px;border-radius: 50%;cursor: pointer;position: relative;box-shadow: 0 2px 8px rgba(0,0,0,0.1);transition: transform 0.2s ease, box-shadow 0.2s ease;flex: 0 0 auto;
}.color-btn.active {transform: scale(1.1);box-shadow: 0 4px 12px rgba(0,0,0,0.15);border: 2px solid white;
}.color-label {position: absolute;top: 100%;left: 50%;transform: translateX(-50%);margin-top: 8px;font-size: 12px;color: #333;white-space: nowrap;
}
接下来我们来实现切换功能,步骤如下
1收集汽车的材质信息
2找到汽车的车身材质,并进行颜色修改
3可以使用tween将颜色的过渡效果实现出来
在加载汽车的时候,就收集到所有的材质信息,并存储到数组中
materials结构,Car_body.004是核心属性
在点击到按钮之后,得到对应的颜色,然后修改材质,我们的车身材质名称为Car_body.004
const changeCarBodyColor=(colorString)=>{console.log(materials);if(materials.length){materials.forEach(m=>{if(m.name.includes('Car_body')){m.color=new THREE.Color(colorString)}})}
}
我们还可以通过Tweenjs来实现动画效果
import * as TWEEN from '@tweenjs/tween.js'let tween
const TweenColorChange=(primColor,color)=>{return new TWEEN.Tween(primColor).to(color, 600).easing(TWEEN.Easing.Linear.None).start()
}
将changeCarBodyColor修改一下
const changeCarBodyColor=(colorString)=>{if(materials.length){materials.forEach(m=>{if(m.name.includes('Car_body')){tween=TweenColorChange(m.color,new THREE.Color(colorString))//m.color=new THREE.Color(colorString)}})}
}
在渲染器中进行更新
renderer.setAnimationLoop(() => {if(tween){tween.update()}camera.lookAt(0,0,0)camera.updateProjectionMatrix();renderer.render(scene, camera);
});
** 4.其他优化细节**
我们仔细观察懂车帝的效果,发现其操作方式只能左右旋转小车,并不能上下偏移
我们可以通过设置轨道控制器的属性达成这一点,并且还可以把相机设置到一个合适的位置
camera.position.set(6.031, 1.39, -5.08);
orbitControl.enablePan = false;
orbitControl.enableZoom = false;
orbitControl.minPolarAngle = (80 * Math.PI) / 180;
orbitControl.maxPolarAngle = (80 * Math.PI) / 180;
最终效果