Vue3 + Three.js 实现 3D 汽车个性化定制及展示

文章目录


前言

在现代web开发中,3D可视化技术正变得越来越流行,特别是在汽车、房地产等行业。本文将详细介绍如何使用Vue 3和Three.js构建一个交互式3D汽车展示系统,实现汽车模型的360°旋转查看、部位选择、颜色定制和材质切换等功能。


一、项目概述

这是一个基于Vue 3 Composition API 和 Three.js 开发的3D汽车展示与个性化定制应用,用户可以通过直观的界面浏览3D汽车模型,并对汽车的不同部位进行颜色和材质的个性化定制。

主要功能包括:

  • 3D汽车模型的加载与展示
  • 模型的360°旋转、缩放和视角调整
  • 汽车不同部位的选择(车身、前脸、引擎盖、轮毂、玻璃等)
  • 多种颜色选择定制
  • 多种贴膜材质效果切换

二、技术栈

前端框架:Vue 3 (Composition API)

3D渲染引擎:Three.js

构建工具:Vite

模型加载:GLTFLoader + DRACOLoader

交互控制:OrbitControls

三、核心功能实现

1.Three.js 基础环境搭建

首先,我们需要在Vue组件中搭建Three.js的基础环境,包括场景、相机、渲染器等核心元素。

javascript 复制代码
<script setup>
import * as THREE from "three";
import { onMounted, ref } from "vue";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";

let canvasDom = ref(null);
// 创建场景
const scene = new THREE.Scene();
// 创建相机
const camera = new THREE.PerspectiveCamera(
  75,
  window.innerWidth / window.innerHeight,
  0.1,
  1000
);
camera.position.set(0, 2, 6);
// 创建渲染器
const renderer = new THREE.WebGLRenderer({
  // 抗锯齿
  antialias: true,
});
renderer.setSize(window.innerWidth, window.innerHeight);

// 渲染循环
const render = () => {
  renderer.render(scene, camera);
  controls && controls.update();
  requestAnimationFrame(render);
};
</script>

2.模型加载与处理

使用GLTFLoader和DRACOLoader加载3D模型,并对模型的不同部位进行识别和处理,为后续的个性化定制做准备。

javascript 复制代码
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
import { DRACOLoader } from "three/examples/jsm/loaders/DRACOLoader";

// 汽车部位存储
let carParts = {
  body: null,
  front: null,
  hood: null,
  glass: null,
  wheels: []
};

onMounted(() => {
  // 把渲染器插入到dom中
  canvasDom.value.appendChild(renderer.domElement);
  // 初始化渲染器,渲染背景
  scene.background = new THREE.Color("#1a1a2e");
  render();

  // 添加控制器
  const controls = new OrbitControls(camera, renderer.domElement);
  controls.update();

  // 添加gltf汽车模型
  const loader = new GLTFLoader();
  const dracoLoader = new DRACOLoader();
  dracoLoader.setDecoderPath("./draco/gltf/");
  loader.setDRACOLoader(dracoLoader);
  
  loader.load("./model/bmw01.glb", (gltf) => {
    const bmw = gltf.scene;

    // 遍历模型,识别不同部位
    bmw.traverse((child) => {
      if (child.isMesh) {
        // 判断是否是轮毂
        if (child.name.includes("轮毂")) {
          child.material = partMaterials.wheels;
          carParts.wheels.push(child);
        }
        // 判断是否是车身
        if (child.name.includes("Mesh002")) {
          carParts.body = child;
          carParts.body.material = partMaterials.body;
        }
        // 其他部位识别类似...
      }
    });
    scene.add(bmw);
  });
  
  // 窗口大小改变时更新渲染器
  window.addEventListener('resize', () => {
    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();
    renderer.setSize(window.innerWidth, window.innerHeight);
  });
});

3.材质系统实现

为汽车的不同部位创建物理材质,并设置颜色和材质的状态管理。

javascript 复制代码
// 颜色列表
const colorList = [
  { name: "红色", value: 0xff0000 },
  { name: "蓝色", value: 0x0000ff },
  { name: "绿色", value: 0x00ff00 },
  { name: "灰色", value: 0x808080 },
  { name: "橙色", value: 0xffa500 },
  { name: "紫色", value: 0x800080 },
  { name: "黑色", value: 0x000000 },
  { name: "白色", value: 0xffffff }
];

// 材质列表
const materialList = [
  { name: "磨砂", clearcoat: 0.3, roughness: 0.8, clearcoatRoughness: 0.9 },
  { name: "金属", clearcoat: 1, roughness: 0.4, clearcoatRoughness: 0.1 },
  { name: "哑光", clearcoat: 0, roughness: 0.7, clearcoatRoughness: 0.2 },
  { name: "镜面", clearcoat: 1, roughness: 0.1, clearcoatRoughness: 0 }
];

// 汽车各部位材质
let partMaterials = {
  body: new THREE.MeshPhysicalMaterial({
    color: 0xff0000,
    metalness: 1,
    roughness: 0.5,
    clearcoat: 1,
    clearcoatRoughness: 0,
  }),
  // 其他部位材质类似...
};

// 当前选中的部位和材质
let selectedPart = ref('all');
let selectedMaterial = ref(1);

4.交互控制实现

实现颜色选择、材质选择和部位选择的交互逻辑。

javascript 复制代码
// 选择颜色
let selectColor = (colorIndex) => {
  const color = colorList[colorIndex].value;
  
  if (selectedPart.value === 'all' || selectedPart.value === 'body') {
    partMaterials.body.color.set(color);
  }
  if (selectedPart.value === 'all' || selectedPart.value === 'front') {
    partMaterials.front.color.set(color);
  }
  // 其他部位颜色设置类似...
};

// 选择材质
let selectMaterial = (materialIndex) => {
  selectedMaterial.value = materialIndex;
  const material = materialList[materialIndex];
  
  if (selectedPart.value === 'all' || selectedPart.value === 'body') {
    partMaterials.body.clearcoat = material.clearcoat;
    partMaterials.body.roughness = material.roughness;
    partMaterials.body.clearcoatRoughness = material.clearcoatRoughness;
  }
  // 其他部位材质设置类似...
};

// 选择汽车部位
let selectPart = (part) => {
  selectedPart.value = part;
};

5.光照系统设置

设置合理的光照系统,提升3D模型的视觉效果。

javascript 复制代码
// 添加灯光
const ambientLight = new THREE.AmbientLight(0xffffff, 0.6);
scene.add(ambientLight);

const light1 = new THREE.DirectionalLight(0xffffff, 1);
light1.position.set(0, 10, 10);
scene.add(light1);

const light2 = new THREE.DirectionalLight(0xffffff, 0.5);
light2.position.set(-10, 10, 0);
scene.add(light2);

const light3 = new THREE.DirectionalLight(0xffffff, 0.3);
light3.position.set(0, -10, 0);
scene.add(light3);

// 添加环境光
const hemisphereLight = new THREE.HemisphereLight(0xffffff, 0x888888, 0.3);
scene.add(hemisphereLight);

四、模板结构与样式

html 复制代码
<template>
  <div class="home">
    <div
      class="canvas-container"
      ref="canvasDom"
    ></div>

    <div class="home-content">
      <div class="home-content-title">
        <h1>3D汽车展示与个性化定制</h1>
      </div>

      <!-- 部位选择 -->
      <h2>选择汽车部位</h2>
      <div class="select">
        <div
          class="select-item part-item"
          v-for="(part, index) in [{ name: '全部', value: 'all' }, /* 其他部位 */]"
          :key="index"
          @click="selectPart(part.value)"
          :class="{ active: selectedPart === part.value }"
        >
          <div class="select-item-text">{{ part.name }}</div>
        </div>
      </div>

      <!-- 颜色选择和材质选择类似 -->
    </div>
  </div>
</template>
<style>
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

.canvas-container {
  width: 100vw;
  height: 100vh;
  overflow: hidden;
}

.home-content {
  position: fixed;
  top: 20px;
  right: 20px;
  background: rgba(255, 255, 255, 0.9);
  backdrop-filter: blur(10px);
  padding: 20px;
  border-radius: 15px;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
  max-width: 300px;
  z-index: 1000;
}

/* 响应式设计 */
@media (max-width: 768px) {
  .home-content {
    position: fixed;
    top: auto;
    bottom: 0;
    right: 0;
    left: 0;
    max-width: none;
    border-radius: 15px 15px 0 0;
  }
}
</style>

总结

通过本项目,我们成功实现了一个基于Vue 3和Three.js的3D汽车展示与个性化定制系统。这个系统不仅可以展示3D汽车模型,还提供了丰富的交互功能,让用户可以实时定制汽车的外观。

未来可以考虑添加以下功能:

  • 更多汽车模型的支持
  • 内饰定制功能
  • 汽车配置保存和分享功能
  • AR/VR展示模式
  • 更多高级材质和纹理效果

这个项目展示了如何在Web应用中集成3D技术,为用户提供更直观、更沉浸的交互体验,通过学习和实践这个项目,开发者可以掌握Vue 3和Three.js的核心概念和技术,为开发更复杂的3D Web应用打下基础。

附gitee项目地址:https://gitee.com/leaving-dust/3d-car-selection

相关推荐
Dontla2 小时前
Turbopack介绍(由Vercel开发的基于Rust的高性能前端构建工具,用于挑战传统构建工具Webpack、vite地位)Next.js推荐构建工具
前端·rust·turbopack
两个西柚呀2 小时前
nodejs中http模块搭建web服务器
服务器·前端·http
安当加密3 小时前
CAS密钥管理系统在汽车行业的核心密钥管理实践——构建智能网联汽车的可信安全底座
网络·安全·汽车
Focusbe3 小时前
百变AI助手:离线优先数据同步方案设计
前端·后端·面试
ObjectX前端实验室4 小时前
React Fiber 双缓冲树机制深度解析
前端·react.js
细节控菜鸡4 小时前
【2025最新】ArcGIS for JS 实现地图卷帘效果,动态修改参数(进阶版)
开发语言·javascript·arcgis
高斯林.神犇4 小时前
javaWeb基础
前端·chrome
用户21411832636024 小时前
dify案例分享-Qwen3-VL+Dify:从作业 OCR 到视频字幕,多模态识别工作流一步教,附体验链接
前端
南屿im5 小时前
把代码变成“可改的树”:一文读懂前端 AST 的原理与实战
前端·javascript