vue3+three.js的理解与简单使用示例代码

 更新时间:2026年02月10日 10:21:01   作者:行咘行啊细狗  
Three.js是一个基于WebGL的开源JavaScript 3D引擎,它简化了Web 3D开发流程,让开发者能够轻松创建3D场景、动画和交互体验,这篇文章主要介绍了vue3+three.js理解与简单使用的相关资料,需要的朋友可以参考下

一、tres.js的安装

npm i @tresjs/core @tresjs/cientos three

二、three.js的一些基本概念

1、Scene(场景,可以想象成一个空房间。):(这里介绍的是three.js的手动创建)

2、Camera(相机)​ - 观众的眼睛

3、 Renderer(渲染器)​ - 摄影师

4、Object(物体)​ - 演员

// 手动创建一切 ⚙️
const scene = new THREE.Scene()           // 手动造房间
const camera = new THREE.PerspectiveCamera() // 手动买相机
const renderer = new THREE.WebGLRenderer() // 手动雇摄影师

// 手动组合所有东西
scene.add(mesh)                          // 手动放家具
scene.add(light)                         // 手动装电灯
renderer.render(scene, camera)           // 手动拍照

记住:没有 Scene(房间),你的 3D 东西就飘在空中,看不见也摸不着!

三、tres.js的简单示例(自动化创建thrss.js的关键要素):

<template>
  <!-- 主容器,确保3D场景充满整个视口 -->
  <div style="width: 100%; height: 100vh">
    <!-- 
      TresCanvas 是 3D 场景的根容器,可以理解成一个工地,它自动创建了:
      1. Scene(场景/空房间)
      2. Renderer(渲染器)
      3. Canvas(画布)
      4. 自动渲染循环
      window-size: 自动填充整个窗口大小
      clear-color: 背景颜色,这里设置为青绿色
    -->
    <TresCanvas window-size clear-color="#82DBC5">
      <!-- 
        透视相机,模拟人眼视角
        :position="[3, 3, 3]": 相机在3D空间中的位置 [x, y, z]
        :look-at="[0, 0, 0]": 相机看向的点 [x, y, z],这里设置为世界原点
      -->
      <TresPerspectiveCamera :position="[3, 3, 3]" :look-at="[0, 0, 0]" />

      <!-- 
        🎮 轨道控制器,提供用户交互功能:
        - 左键拖拽:旋转场景
        - 右键拖拽:平移场景  
        - 滚轮缩放:缩放场景
        无需额外配置,开箱即用
      -->
      <OrbitControls />

      <!-- 
        📦 立方体网格
        TresMesh可以理解成工地的某一栋房子,包含几何体和材质
      -->
      <TresMesh>
        <!-- 
          📐 立方体几何体,定义形状
          :args="[1, 1, 1]": 定义立方体的尺寸 [宽度, 高度, 深度]
        -->
        <TresBoxGeometry :args="[1, 1, 1]" />
        <!-- 
          🎨 基础网格材质,为几何体添加外观属性
          color="red": 基础颜色设置为红色
          :wireframe="true": 启用线框模式,只显示边框
        -->
        <TresMeshBasicMaterial color="red" :wireframe="true" />
      </TresMesh>

      <!-- 
        💡 环境光,模拟环境反射光
        :intensity="0.8": 光照强度为0.8
        环境光无方向性,为整个场景提供均匀的基础照明
      -->
      <TresAmbientLight :intensity="0.8" />

      <!-- 
        🎯 坐标轴辅助工具,帮助理解3D空间方向
        :args="[5]": 坐标轴长度为5个单位
        红色=X轴,绿色=Y轴,蓝色=Z轴
      -->
      <TresAxesHelper :args="[5]" />
    </TresCanvas>
  </div>
</template>

<script setup>
// 导入Tres.js核心组件
import { TresCanvas } from "@tresjs/core";
// 导入轨道控制器组件
import { OrbitControls } from "@tresjs/cientos";
</script>

四、效果图:

五、tres.js实现iphone手机3D模型组件展示:

<template>
  <div class="iphone-showcase">
    <!-- 
      TresCanvas是Tres.js的根组件,相当于Three.js的WebGL渲染器
      window-size: 自动填充整个窗口大小
      :clear-color: 绑定背景颜色,使用Vue的响应式数据
    -->
    <TresCanvas window-size :clear-color="currentColor">
      <!-- 
        透视相机组件
        :position: 相机在3D空间中的位置 [x, y, z]
        :look-at: 相机看向的点 [x, y, z],这里设置为世界原点
        :fov: 视野角度,60度是接近人眼的自然视角
      -->
      <TresPerspectiveCamera
        :position="[cameraPosition.x, cameraPosition.y, cameraPosition.z]"
        :look-at="[0, 0, 0]"
        :fov="60"
      />

      <!-- 
        轨道控制器,提供用户交互功能:
        - 左键拖拽:旋转场景
        - 右键拖拽:平移场景  
        - 鼠标滚轮:缩放场景
        enable-damping: 启用阻尼效果,使移动更平滑
        damping-factor: 阻尼系数,值越小移动越平滑
        :auto-rotate: 绑定自动旋转状态
        auto-rotate-speed: 自动旋转的速度
      -->
      <OrbitControls
        enable-damping
        damping-factor="0.05"
        :auto-rotate="autoRotate"
        auto-rotate-speed="1"
      />

      <!-- 光源系统 -->
      <!-- 平行光:模拟太阳光,有明确的方向性,产生阴影 -->
      <TresDirectionalLight :position="[5, 5, 5]" :intensity="1.5" />
      <!-- 环境光:模拟环境反射光,无方向,提供基础照明 -->
      <TresAmbientLight :intensity="0.8" />
      <!-- 点光源:模拟灯泡,从点向四周发射光线 -->
      <TresPointLight :position="[2, 3, -2]" :intensity="0.8" color="#4ecdc4" />

      <!-- iPhone模型组件 -->
      <IPhoneModel />

      <!-- 辅助工具(主要用于调试) -->
      <!-- 坐标轴辅助:红色=X轴,绿色=Y轴,蓝色=Z轴,帮助理解3D空间方向 -->
      <TresAxesHelper :args="[3]" />
      <!-- 网格辅助:10x10的网格,帮助定位和观察场景比例 -->
      <TresGridHelper :args="[10, 10]" :position="[0, -1.5, 0]" />
    </TresCanvas>

    <!-- 控制面板 -->
    <div class="controls">
      <button @click="toggleAutoRotate">
        {{ autoRotate ? "⏸️ 暂停" : "▶️ 旋转" }}
      </button>
      <button @click="changeColor">🎨 换色</button>
    </div>
  </div>
</template>

<script setup>
import {
  ref,
  reactive,
  onMounted,
  onUnmounted,
  watch,
  h,
  shallowRef,
} from "vue";
import { TresCanvas } from "@tresjs/core";
import { OrbitControls } from "@tresjs/cientos";
import * as THREE from "three";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";

//自动旋转控制,初始值为true(启用自动旋转)
const autoRotate = ref(true);

/**
 * 相机位置
 * reactive用于对象类型数据,初始位置为[0, 0.5, 3]
 * - x: 水平位置
 * - y: 垂直位置
 * - z: 深度位置
 */
const cameraPosition = reactive({ x: 0, y: 0.5, z: 3 });

//背景颜色
const currentColor = ref("#1a1a2e");

/**
 * iPhone模型引用
 * 使用shallowRef优化性能,只对.value的变化做出响应
 */
const iphoneModel = shallowRef(null);

// ========== 动画循环控制 ==========

// 动画帧ID,用于控制动画循环
let animationId = null;

// ========== 用户交互方法 ==========

//旋转、暂停
const toggleAutoRotate = () => {
  autoRotate.value = !autoRotate.value;
};

//换色
const changeColor = () => {
  const colors = ["#1a1a2e", "#0f3460", "#533483", "#16213e"];
  const currentIndex = colors.indexOf(currentColor.value);
  currentColor.value = colors[(currentIndex + 1) % colors.length];
};

// ========== 模型加载逻辑 ==========

//加载iPhone模型
const loadIPhoneModel = () => {
  // 创建GLTF加载器实例(GLTFLoader是加载GLTF格式的3D模型文件)
  const loader = new GLTFLoader();
  // 模型文件路径(需要放在public/models/目录下)
  const modelPath = "/models/scene.gltf";

  /**
   * 加载GLTF模型
   * 参数1: 模型文件路径
   * 参数2: 加载成功回调函数
   * 参数3: 加载进度回调函数
   * 参数4: 加载失败回调函数
   */
  loader.load(
    modelPath,
    // 加载成功回调
    // const gltf = {
    //   scene: THREE.Group,        // 整个3D场景(最重要的部分)
    //   scenes: Array,             // 场景数组(通常只有一个场景)
    //   cameras: Array,            // 相机数组
    //   animations: Array,         // 动画数据数组
    //   asset: Object,             // 资源信息(作者、版本等)
    //   userData: Object           // 用户自定义数据
    // };
    (gltf) => {
      // 检查场景是否有效
      if (gltf.scene) {
        // 克隆模型,避免直接修改原始数据
        const model = gltf.scene.clone();
        //确保模型正确显示。网格(Mesh):3D模型的基本组成单位,包含几何体(形状)和材质(外观)
        model.traverse((child) => {
          if (child.isMesh) {
            child.visible = true;
          }
        });

        //创建一个刚好能完全包围这个3D模型的矩形边界框,用于获取模型的精确尺寸和位置信息,以便进行居中、缩放等标准化处理。
        const box = new THREE.Box3().setFromObject(model);
        // 获取模型尺寸
        const size = box.getSize(new THREE.Vector3());
        // 获取模型中心点
        const center = box.getCenter(new THREE.Vector3());
        // 将模型移动到世界原点(0,0,0)
        model.position.x -= center.x;
        model.position.y -= center.y;
        model.position.z -= center.z;
        // 根据最大尺寸缩放模型到合适大小
        const maxSize = Math.max(size.x, size.y, size.z);
        // 缩放到0.8单位大小,确保模型不会太大或太小
        const scale = maxSize > 0 ? 0.8 / maxSize : 1;
        model.scale.setScalar(scale);

        // 更新模型引用
        iphoneModel.value = model;
      }
    },
    // 加载进度回调
    // const progress = {
    //   loaded: 1024000,        // 已加载的字节数 (bytes)
    //   total: 5120000,         // 总字节数 (bytes)
    //   lengthComputable: true  // 是否知道总大小
    // };
    (progress) => {
      // 在控制台显示加载进度,便于调试
      console.log(
        `加载进度: ${((progress.loaded / progress.total) * 100).toFixed(2)}%`
      );
    },
    // 加载失败回调
    (error) => {
      console.error("模型加载失败:", error);
    }
  );
};

// ========== iPhone模型组件 ==========

const IPhoneModel = () => {
  if (iphoneModel.value) {
    // 模型已加载:渲染3D模型
    return h("primitive", { object: iphoneModel.value });
  }
  // 模型未加载:不渲染内容
  return null;
};

// ========== 动画系统 ==========

const animate = () => {
  // 1. 动画函数定义
  if (autoRotate.value) {
    // 2. 动画条件控制
    const time = Date.now() * 0.001; // 3. 时间变量
    cameraPosition.x = Math.sin(time) * 3; // 4. 属性变化(动画核心)
    cameraPosition.z = Math.cos(time) * 3;
  }
  animationId = requestAnimationFrame(animate); // 5. 循环机制
};

//开始动画循环
const startAnimation = () => {
  if (!animationId) {
    animationId = requestAnimationFrame(animate);
  }
};

//停止动画循环
const stopAnimation = () => {
  if (animationId) {
    cancelAnimationFrame(animationId);
    animationId = null; // 重置ID
  }
};

// ========== 响应式监听和生命周期 ==========

//监听旋转还是暂停
watch(autoRotate, (newVal) => {
  if (newVal) {
    startAnimation(); // 开始动画循环
  } else {
    stopAnimation(); // 停止动画循环
  }
});

onMounted(() => {
  if (autoRotate.value) {
    startAnimation(); // 开始动画循环
  }
  // 加载iPhone模型
  loadIPhoneModel();
});

onUnmounted(() => {
  stopAnimation(); // 停止动画循环,避免内存泄漏
});
</script>

<style scoped>
/* 主容器样式 */
.iphone-showcase {
  width: 100%;
  height: 100vh;
  position: relative;
}

/* 控制面板样式 */
.controls {
  position: absolute;
  bottom: 20px;
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  gap: 10px;
  z-index: 100;
}

/* 控制按钮样式 */
.controls button {
  padding: 10px 20px;
  background: rgba(255, 255, 255, 0.9);
  border: none;
  border-radius: 25px;
  color: #333;
  font-weight: 600;
  cursor: pointer;
  transition: all 0.3s ease;
}

/* 按钮悬停效果 */
.controls button:hover {
  background: rgba(255, 255, 255, 1);
  transform: translateY(-2px);
}
</style>

六、iphone手机3D模型组件下载:

这里使用的是Sketchfab下载的3D模型文件,这里使用的是gltf文件(下载后需要解压,然后将全部的解压文件放到public/models中即可)

七、效果图:

总结 

到此这篇关于vue3+three.js理解与简单使用的文章就介绍到这了,更多相关vue3 three.js简单使用内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 关于Vue 消除Token过期时刷新页面的重复提示问题

    关于Vue 消除Token过期时刷新页面的重复提示问题

    很多朋友在token过期时刷新页面,页面长时间未操作,再刷新页面时,第一次弹出“token失效,请重新登录!”提示,针对这个问题该怎么处理呢,下面小编给大家带来原因分析及解决方法,一起看看吧
    2021-07-07
  • vuex中遇到的坑,vuex数据改变,组件中页面不渲染操作

    vuex中遇到的坑,vuex数据改变,组件中页面不渲染操作

    这篇文章主要介绍了vuex中遇到的坑,vuex数据改变,组件中页面不渲染操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-11-11
  • 深度剖析 Vue3 在浏览器的运行原理

    深度剖析 Vue3 在浏览器的运行原理

    这篇文章主要介绍了深度剖析Vue3在浏览器的运行原理,文章通过围绕主题展开相关详细介绍,具有一定的参考价值,需要的小伙伴可以参考一下
    2022-09-09
  • vue多层嵌套路由实例分析

    vue多层嵌套路由实例分析

    这篇文章主要介绍了vue多层嵌套路由,结合实例形式分析了vue.js多层嵌套路由的概念、原理及相关操作技巧,需要的朋友可以参考下
    2019-03-03
  • Cookbook组件形式:优化 Vue 组件的运行时性能

    Cookbook组件形式:优化 Vue 组件的运行时性能

    本文仿照Vue Cookbook 组织形式,对优化 Vue 组件的运行时性能进行阐述。通过基本的示例代码给大家讲解,需要的朋友参考下
    2018-11-11
  • element-ui使用导航栏跳转路由的用法详解

    element-ui使用导航栏跳转路由的用法详解

    今天小编就为大家分享一篇element-ui使用导航栏跳转路由的用法详解,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-08-08
  • vue 插槽简介及使用示例

    vue 插槽简介及使用示例

    这篇文章主要介绍了vue 插槽简介及使用示例,帮助大家更好的理解和学习vue框架,感兴趣的朋友可以了解下
    2020-11-11
  • 一文详解Vue3中简单diff算法的实现

    一文详解Vue3中简单diff算法的实现

    这篇文章主要为大家详细介绍Vue3中简单diff算法的实现与使用,文中的示例代码讲解详细,具有一定的借鉴价值,感兴趣的可以了解一下
    2022-09-09
  • Element UI安装全过程

    Element UI安装全过程

    element ui 就是基于vue的一个ui框架,该框架基于vue开发了很多相关组件,方便我们快速开发页面,饿了么前端团队基于vue进行开发并且进行了开源 element ui 中提供全部都是封装好组件,本文给大家介绍Element UI安装全过程,感兴趣的朋友一起看看吧
    2024-01-01
  • vue项目开发环境工具node搭建过程

    vue项目开发环境工具node搭建过程

    最近在开始接触做vue框架的前端项目,以前用的前端比如html,js,css等都是比较原生的,写好后直接浏览器打开就行,今天就先记录一下vue的开发运行搭建过程,感兴趣的朋友一起看看吧
    2023-09-09

最新评论