颜色切换
接下来我们来实现懂车帝的颜色切换效果
可以让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;
最终效果