Vue2 结合 Three.js 基础教程

本教程基于提供的代码示例,将带你了解如何在 Vue2 中集成 Three.js 并创建交互式 3D 场景。假设你已具备基本的 Three.js 知识,我们将重点讲解两者结合的关键点。


环境准备

首先需要引入必要的库文件:

<!-- 引入Vue 2 -->
<script src='https://unpkg.com/vue@2.7.14/dist/vue.min.js'></script>

<!-- 引入Three.js核心库 -->
<script src="https://unpkg.com/three@0.128.0/build/three.min.js"></script>

<!-- 引入Three.js轨道控制器 -->
<script src="https://unpkg.com/three@0.128.0/examples/js/controls/OrbitControls.js"></script>

基础结构搭建

HTML 结构

<div id="app">
    <div class="scene-container">
        <!-- 3D场景容器 -->
        <canvas id="three-container"></canvas>
        
        <!-- 交互按钮 -->
        <button class="add-button" @click="addRandomObject">+ 添加随机物体</button>
    </div>
</div>

CSS 样式

关键是设置容器尺寸和定位,确保 Three.js 渲染的画布能正确显示:

#three-container {
    width: 100%;
    height: 100%;
    position: absolute;
}

.add-button {
    position: absolute;
    /* 其他样式... */
    z-index: 10; /* 确保按钮在3D场景上方 */
}

Vue 实例与 Three.js 集成

核心变量定义

在 Vue 实例的data中存储 Three.js 核心对象:

data: {
    // Three.js相关变量
    scene: null,      // 场景
    camera: null,     // 相机
    renderer: null,   // 渲染器
    controls: null,   // 控制器
}

生命周期管理

在 Vue 生命周期钩子中处理 Three.js 初始化和资源清理:

mounted() {
    // 组件挂载时初始化场景
    this.initThreeScene();
    // 监听窗口大小变化
    window.addEventListener('resize', this.onWindowResize);
},
beforeDestroy() {
    // 组件销毁前清理资源
    window.removeEventListener('resize', this.onWindowResize);
    if (this.controls) this.controls.dispose();
    if (this.renderer) this.renderer.dispose();
}

场景初始化流程

initThreeScene方法是整个 3D 场景的入口,包含以下关键步骤:

1. 创建场景

this.scene = new THREE.Scene();
this.scene.background = new THREE.Color(0x0a0a1a); // 设置背景色

2. 创建相机

this.camera = new THREE.PerspectiveCamera(
    75, // 视野角度
    container.clientWidth / container.clientHeight, // 宽高比
    0.1, // 近裁剪面
    1000 // 远裁剪面
);
this.camera.position.set(5, 5, 10); // 设置相机位置

3. 创建渲染器

this.renderer = new THREE.WebGLRenderer({
    canvas: container, // 绑定到指定canvas元素
    antialias: true   // 启用抗锯齿
});
this.renderer.setSize(container.clientWidth, container.clientHeight);

4. 添加控制器

this.controls = new THREE.OrbitControls(this.camera, this.renderer.domElement);
this.controls.enableDamping = true; // 启用阻尼效果
this.controls.dampingFactor = 0.05;

5. 初始化场景内容

this.createInitialObjects(); // 创建初始物体
this.createLights();         // 创建光源
this.animate();              // 启动动画循环

关键功能实现

创建物体

使用Mesh类创建物体,需要几何体(Geometry)和材质(Material):

// 创建立方体示例
const cubeGeometry = new THREE.BoxGeometry(2, 2, 2);
const cubeMaterial = new THREE.MeshPhongMaterial({
    color: 0x4361ee
});
const cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
cube.position.set(-3, 1, 0);
this.scene.add(cube);

光源设置

合适的光照是显示 3D 物体的关键:

// 环境光 - 均匀照亮所有物体
const ambientLight = new THREE.AmbientLight(0xffffff, 0.4);
this.scene.add(ambientLight);

// 平行光 - 模拟太阳光
const directionalLight = new THREE.DirectionalLight(0xffffff, 1.0);
directionalLight.position.set(5, 10, 7);
this.scene.add(directionalLight);

动画循环

Three.js 动画通过requestAnimationFrame实现:

animate() {
    requestAnimationFrame(this.animate); // 递归调用形成循环
    this.controls.update();              // 更新控制器状态
    this.renderer.render(this.scene, this.camera); // 渲染场景和相机
}

交互功能

通过 Vue 的事件绑定实现交互:

<!-- 模板中的按钮 -->
<button class="add-button" @click="addRandomObject">+ 添加随机物体</button>
// 方法实现
addRandomObject() { 
    // 添加随机物体的逻辑
}

响应窗口大小变化

确保场景在窗口大小改变时正确显示:

onWindowResize() {
    this.camera.aspect = window.innerWidth / window.innerHeight;
    this.camera.updateProjectionMatrix();
    this.renderer.setSize(window.innerWidth, window.innerHeight);
}

总结

本节课展示了 Vue2 与 Three.js 结合的基本模式:

  1. 利用 Vue 的生命周期管理 Three.js 资源
  2. 在 Vue 实例中存储 Three.js 核心对象
  3. 通过 Vue 事件系统实现与 3D 场景的交互
  4. 遵循 Three.js 基本工作流程(场景→相机→渲染器→物体→光源)

这种整合方式既保留了 Vue 的响应式和组件化特性,又能充分利用 Three.js 的 3D 渲染能力,适合开发交互式 3D 应用。


提示

本教程展示了如何在 Vue2 中集成 Three.js 并创建基础的 3D 场景。通过结合 Vue 的响应式特性和 Three.js 的强大 3D 渲染能力,可以构建出丰富的交互式 3D 应用。