通过vue如何利用 Three 绘制 简单3D模型(源码案例)

目录

Three 介绍

创建基础3D场景

创建不同类型的3D模型

1. 球体

2. 圆柱体​​​​​​​

3. 平面​​​​​​​

加载外部3D模型

添加交互控制

创建可交互的3D场景


The ship.energy summit – the three key takeaways | ship.energy

Three 介绍

Three.js是一个强大的JavaScript 3D库,可以轻松地在网页中创建3D图形。下面我将介绍如何在Vue项目中使用Three.js创建简单的3D模型。

官网

https://threejs.org/

创建 vue 项目

npm create vue@latest

安装 three

npm install three

项目拖入IDE

创建基础3D场景

<template>  <div ref="container" class="three-container"></div></template><script>import * as THREE from 'three';export default {  name: 'Simple3DModel',  mounted() {    this.initThreeJS();  },  methods: {    initThreeJS() {      // 1. 创建场景      const scene = new THREE.Scene();      scene.background = new THREE.Color(0xf0f0f0);      // 2. 创建相机      const camera = new THREE.PerspectiveCamera(        75, // 视野角度        this.$refs.container.clientWidth / this.$refs.container.clientHeight, // 宽高比        0.1, // 近截面        1000 // 远截面      );      camera.position.z = 5;      // 3. 创建渲染器      const renderer = new THREE.WebGLRenderer({ antialias: true });      renderer.setSize(        this.$refs.container.clientWidth,        this.$refs.container.clientHeight      );      this.$refs.container.appendChild(renderer.domElement);      // 4. 添加光源      const ambientLight = new THREE.AmbientLight(0xffffff, 0.5);      scene.add(ambientLight);      const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8);      directionalLight.position.set(1, 1, 1);      scene.add(directionalLight);      // 5. 创建简单几何体      const geometry = new THREE.BoxGeometry(1, 1, 1);      const material = new THREE.MeshStandardMaterial({         color: 0x00ff00,        metalness: 0.1,        roughness: 0.5      });      const cube = new THREE.Mesh(geometry, material);      scene.add(cube);      // 6. 动画循环      const animate = () => {        requestAnimationFrame(animate);        cube.rotation.x += 0.01;        cube.rotation.y += 0.01;        renderer.render(scene, camera);      };      animate();      // 7. 处理窗口大小变化      window.addEventListener('resize', () => {        camera.aspect = this.$refs.container.clientWidth / this.$refs.container.clientHeight;        camera.updateProjectionMatrix();        renderer.setSize(          this.$refs.container.clientWidth,          this.$refs.container.clientHeight        );      });      // 保存实例以便销毁时清理      this.scene = scene;      this.camera = camera;      this.renderer = renderer;      this.cube = cube;    }  },  beforeDestroy() {    // 清理资源    if (this.renderer) {      this.renderer.dispose();      this.$refs.container.removeChild(this.renderer.domElement);    }    window.removeEventListener('resize', this.handleResize);  }};</script><style>.three-container {  width: 100%;  height: 500px;}</style>

创建不同类型的3D模型

1. 球体​​​​​​​

const geometry = new THREE.SphereGeometry(1, 32, 32);const material = new THREE.MeshStandardMaterial({   color: 0x4169e1,  wireframe: false });const sphere = new THREE.Mesh(geometry, material);scene.add(sphere);

2. 圆柱体​​​​​​​

const geometry = new THREE.CylinderGeometry(0.5, 0.5, 2, 32);const material = new THREE.MeshStandardMaterial({ color: 0xff6347 });const cylinder = new THREE.Mesh(geometry, material);scene.add(cylinder);

3. 平面​​​​​​​

const geometry = new THREE.PlaneGeometry(5, 5);const material = new THREE.MeshStandardMaterial({   color: 0xcccccc,  side: THREE.DoubleSide});const plane = new THREE.Mesh(geometry, material);plane.rotation.x = Math.PI / 2; // 旋转使其水平scene.add(plane);

加载外部3D模型

Three.js支持加载多种格式的3D模型,如GLTF、OBJ、FBX等。以下是加载GLTF模型的示例:

首先安装GLTF加载器:​​​​​​​

npm install three @types/three --savenpm install three-gltf-loader

在组件中使用:​​​​​​​

import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';// 在methods中添加loadModel() {  const loader = new GLTFLoader();  loader.load(    '/path/to/model.gltf',    (gltf) => {      this.scene.add(gltf.scene);    },    undefined,    (error) => {      console.error('An error happened:', error);    }  );}

添加交互控制

可以使用OrbitControls来添加鼠标交互控制:

安装:

npm install three-orbitcontrols
    import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';// 在initThreeJS方法中添加const controls = new OrbitControls(camera, renderer.domElement);controls.enableDamping = true; // 启用阻尼效果controls.dampingFactor = 0.05;// 在animate函数中更新controlscontrols.update();

    完整的案例

    创建可交互的3D场景

      <template>  <div ref="container" class="three-container"></div></template><script>import * as THREE from 'three';import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';export default {  name: 'Interactive3DScene',  mounted() {    this.initThreeJS();  },  methods: {    initThreeJS() {      // 场景      const scene = new THREE.Scene();      scene.background = new THREE.Color(0xf0f0f0);            // 相机      const camera = new THREE.PerspectiveCamera(        75,        this.$refs.container.clientWidth / this.$refs.container.clientHeight,        0.1,        1000      );      camera.position.set(0, 2, 5);            // 渲染器      const renderer = new THREE.WebGLRenderer({ antialias: true });      renderer.setSize(        this.$refs.container.clientWidth,        this.$refs.container.clientHeight      );      renderer.shadowMap.enabled = true;      this.$refs.container.appendChild(renderer.domElement);            // 控制器      const controls = new OrbitControls(camera, renderer.domElement);      controls.enableDamping = true;      controls.dampingFactor = 0.05;            // 光源      const ambientLight = new THREE.AmbientLight(0xffffff, 0.5);      scene.add(ambientLight);            const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8);      directionalLight.position.set(5, 10, 7);      directionalLight.castShadow = true;      directionalLight.shadow.mapSize.width = 1024;      directionalLight.shadow.mapSize.height = 1024;      scene.add(directionalLight);            // 地面      const groundGeometry = new THREE.PlaneGeometry(10, 10);      const groundMaterial = new THREE.MeshStandardMaterial({         color: 0xcccccc,        side: THREE.DoubleSide      });      const ground = new THREE.Mesh(groundGeometry, groundMaterial);      ground.rotation.x = -Math.PI / 2;      ground.receiveShadow = true;      scene.add(ground);            // 添加一些3D物体      this.addObjects(scene);            // 动画循环      const animate = () => {        requestAnimationFrame(animate);        controls.update();        renderer.render(scene, camera);      };            animate();            // 窗口大小调整      window.addEventListener('resize', this.handleResize);            // 保存实例      this.scene = scene;      this.camera = camera;      this.renderer = renderer;      this.controls = controls;    },        addObjects(scene) {      // 立方体      const cubeGeometry = new THREE.BoxGeometry(1, 1, 1);      const cubeMaterial = new THREE.MeshStandardMaterial({         color: 0x00ff00,        metalness: 0.3,        roughness: 0.4      });      const cube = new THREE.Mesh(cubeGeometry, cubeMaterial);      cube.position.set(-2, 0.5, 0);      cube.castShadow = true;      scene.add(cube);            // 球体      const sphereGeometry = new THREE.SphereGeometry(0.7, 32, 32);      const sphereMaterial = new THREE.MeshStandardMaterial({         color: 0x4169e1,        metalness: 0.5,        roughness: 0.1      });      const sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);      sphere.position.set(0, 0.7, 0);      sphere.castShadow = true;      scene.add(sphere);            // 圆柱体      const cylinderGeometry = new THREE.CylinderGeometry(0.5, 0.5, 1.5, 32);      const cylinderMaterial = new THREE.MeshStandardMaterial({         color: 0xff6347,        metalness: 0.1,        roughness: 0.8      });      const cylinder = new THREE.Mesh(cylinderGeometry, cylinderMaterial);      cylinder.position.set(2, 0.75, 0);      cylinder.castShadow = true;      scene.add(cylinder);    },        handleResize() {      this.camera.aspect = this.$refs.container.clientWidth / this.$refs.container.clientHeight;      this.camera.updateProjectionMatrix();      this.renderer.setSize(        this.$refs.container.clientWidth,        this.$refs.container.clientHeight      );    }  },  beforeDestroy() {    if (this.renderer) {      this.renderer.dispose();      this.$refs.container.removeChild(this.renderer.domElement);    }    window.removeEventListener('resize', this.handleResize);  }};</script><style>.three-container {  width: 100%;  height: 500px;}</style>

      * Thanks you *

      如果觉得文章内容不错,随手帮忙点个赞在看转发一下,如果想第一时间收到推送,也可以给我个星标⭐~谢谢你看我的文章。


      *往期推荐 *

      实现如何利用 Kafka 延时删除 用户邮箱的验证码(如何发送邮箱+源码) - 第一期

      Docker小白入门教程一篇领你入门(CRUD全命令+无废话版+问题集)-第三期

      Docker小白入门教程一篇领你入门(CRUD全命令+无废话版+问题集)

      想要高效处理,那不妨看看 Python的 异步 Asyncio 保证效率翻多倍

      银河麒麟 | ubuntu 安装国产达梦DM8数据库(安装+外网通+IDEA连接)

      网络设备日志存储到指定的Kiwi-log服务器(图解+软件)

      银河麒麟 | ubuntu 安装运用 docker 容器,实现容器化部署项目

      银河麒麟 | ubuntu 安装zabbix监控设备信息(亲测包对)

      国产操作系统-银河麒麟本地化部署Ollama国产开源的AI大模型Qwen3

      Ubuntu |  安装 Zabbix 一篇就够了

      Swagger | 手把手带你写自动生成接口文档的爽感(零基础亲测实用)

      SpringBoot整合Openfeign接入Kimi Ai!!超简单,居然没多少行代码??(附加兜底教程)

      SpringBoot接入Kimi实践记录轻松上手

      Linux | 零基础Ubuntu搭建JDK

      Maven | 站在初学者的角度配置与项目创建(新手必学会)

      Spring Ai | 极简代码从零带你一起走进AI项目(中英)

      Open Ai | 从零搭建属于你的Ai项目(中英结合)

      MongoDB | 零基础学习与Springboot整合ODM实现增删改查(附源码)

      Openfeign | 只传递城市代码,即可获取该地域实时的天气数据(免费的天气API)

      Redis | 缓存技术对后端的重要性,你知道多少?

      Mongodb | 基于Springboot开发综合社交网络应用的项目案例(中英)


      感谢阅读 | 更多内容尽在公棕号 WMCode | CSDN@小Mie不吃饭

      本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
      如若转载,请注明出处:http://www.pswp.cn/bicheng/88386.shtml
      繁体地址,请注明出处:http://hk.pswp.cn/bicheng/88386.shtml

      如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

      相关文章

      云蝠智能 Voice Agent 落地展会邀约场景:重构会展行业的智能交互范式

      一、行业痛点与 AI 破局在会展行业数字化转型的浪潮中&#xff0c;传统展会邀约模式面临多重挑战&#xff1a;人工外呼日均仅能处理 300-500 通电话&#xff0c;且无效号码占比高达 40% 以上&#xff0c;导致邀约效率低下。同时&#xff0c;个性化邀约话术设计依赖经验&#xf…

      idea如何打开extract surround

      在 IntelliJ IDEA 中&#xff0c;"Extract Surrounding"&#xff08;提取周围代码&#xff09;通常指 ​将一段代码提取到新的方法、变量或类中&#xff0c;但更常见的操作是 ​​"Surround With"&#xff08;用代码结构包围&#xff09;​。以下是两种场景…

      window显示驱动开发—XR_BIAS 和 BltDXGI

      Direct3D 运行时调用驱动程序的 BltDXGI 函数&#xff0c;以仅对XR_BIAS源资源执行以下操作&#xff1a;复制到也XR_BIAS的目标未修改的源数据的副本可接受点样本的拉伸旋转由于 XR_BIAS 不支持 MSAA) (多个示例抗锯齿&#xff0c;因此驱动程序不需要解析XR_BIAS资源。核心规则…

      web网页开发,在线%ctf管理%系统,基于html,css,webform,asp.net mvc, sqlserver, mysql

      webform,asp.net mvc。数据库支持mysql,sqlserver经验心得 每次我们写crud没啥技术含量&#xff0c;这没法让咱们进入大厂&#xff0c;刚好这次与客户沟通优化方案建议&#xff0c;咱们就把能加的帮他都加上去。一个ctf管理系统基本crud&#xff0c;并进行不同分层开发&#xf…

      面试技术问题总结一

      MySQL的几种锁机制一、从锁的粒度角度划分表级锁机制&#xff1a;它是对整张表进行锁定的一种锁。当一个事务对表执行写操作时&#xff0c;会获取写锁&#xff0c;在写锁持有期间&#xff0c;其他事务无法对该表进行读写操作&#xff1b;而当事务执行读操作时&#xff0c;会获取…

      π0.5的KI改进版——知识隔离:让VLM在不受动作专家负反馈的同时,继续输出离散动作token,并根据反馈做微调(而非冻结VLM)

      前言 过去的一个月(25年6.4-7.4)&#xff0c;我司「七月在线」具身长沙分部为冲刺一些为客户来现场看的演示项目&#xff0c;基本都用lerobot的那套框架 比如上周五(7.4日)晚上&#xff0c;通过上周五下午新采的第五波数据做『耳机线插入耳机孔』的任务&#xff0c;推理十次之…

      Eigen中Isometry3d的使用详解和实战示例

      Eigen::Isometry3d 是 Eigen 库中用于表示 三维空间中的刚性变换&#xff08;Rigid Transformation&#xff09; 的类&#xff0c;属于 Eigen::Transform 模板类的一个特化版本。它结合了 旋转和平移&#xff0c;广泛应用于机器人学、SLAM、三维几何计算等场景。一、核心定义 #…

      《未来已来:当人类智慧遇上AI智能体》

      在这个充满奇迹的时代,人类的智慧与科技的力量正以前所未有的速度交织在一起。 我们站在一个新时代的门槛上,一边是古老而深邃的自然规律,另一边是充满可能性的未来世界。 今天,就让我们一起走进这场关于人类智慧与AI智能体Kimi的对话,看看未来究竟会带给我们怎样的惊喜…

      【三维生成】FlashDreamer:基于扩散模型的单目图像到3D场景

      标题&#xff1a;<Enhancing Monocular 3D Scene Completion with Diffusion Model> 代码&#xff1a;https://github.com/CharlieSong1999/FlashDreamer 来源&#xff1a;澳大利亚国立大学 文章目录摘要一、前言二、相关工作2.1 场景重建2.2 扩散模型2.3 Vision languag…

      CANFD记录仪设备在无人驾驶快递车的应用

      随着物流行业的快速发展&#xff0c;无人驾驶快递车因其高效、低成本的优势&#xff0c;逐渐成为“最后一公里”配送的重要解决方案。然而&#xff0c;无人驾驶系统的稳定性和安全性高度依赖车辆总线数据的精准采集与分析。南金研CANFDlog4 4路记录仪凭借其多通道、高带宽、高可…

      Kubernetes存储入门

      目录 前言 一、Volume 的概念 二、Volume 的类型 常见的卷类型 Kubernetes 独有的卷类型 三、通过 emptyDir 共享数据 1. 编写 emptyDir 的 Deployment 文件 2. 部署该 Deployment 3. 查看部署结果 4. 登录 Pod 中的第一个容器 5. 登录 Pod 中的第二个容器查看/mnt下…

      10.Docker安装mysql

      (1)docker pull mysql:版本号eg&#xff1a;docker pull mysql(默认安装最新版本)docker pull mysql:5.7(2)启动并设置mysql镜像docker run -d -p 3306:3306 -e MYSQL_ROOT_PASSWORD123456 --name mysql1 mysql其他参数都不多讲&#xff0c;下面这个参数指的是设置数据库用户ro…

      Debian-10编译安装Mysql-5.7.44 笔记250706

      Debian-10编译安装Mysql-5.7.44 笔记250706 单一脚本安装 ### 1. 安装编译依赖 sudo apt install -y cmake gcc g build-essential libncurses5-dev libssl-dev \ pkg-config libreadline-dev zlib1g-dev bison curl wget libaio-dev \ libjson-perl libnuma-dev libsystemd-d…

      HarmonyOS 中状态管理 V2和 V1 的区别

      鸿蒙ArkUI框架中的ComponentV2与V1在状态管理、组件开发模式、性能优化等方面存在显著差异。以下是两者的核心区别及技术解析&#xff1a;一、状态管理机制V1的局限性V1的Observed装饰器只能观察对象的第一层属性变化&#xff0c;需配合ObjectLink手动拆解嵌套对象。例如&#…

      centos7 安装jenkins

      文章目录前言一、pandas是什么&#xff1f;二、安装依赖环境1.前提准备2.安装git3.安装jdk&#xff0c;以及jdk版本选择4.安装maven5.安装NodeJS6.验证三、安装Jenkins四、验证Jenkins总结前言 正在学习jenkinsdocker部署前后端分离项目&#xff0c;安装jenkins的时候遇到了一…

      Leetcode刷题营第二十题:删除链表中的重复节点

      面试题 02.01. 移除重复节点 编写代码&#xff0c;移除未排序链表中的重复节点。保留最开始出现的节点。 示例1&#xff1a; 输入&#xff1a;[1, 2, 3, 3, 2, 1]输出&#xff1a;[1, 2, 3]示例2&#xff1a; 输入&#xff1a;[1, 1, 1, 1, 2]输出&#xff1a;[1, 2]提示&…

      关于市场主流自动化测试工具和框架的简要介绍

      下面我会分别讲解 Selenium、Appium、Playwright 等主流自动化框架的区别、联系、适用场景和归属范畴&#xff0c;帮助你更系统地理解它们。&#x1f527; 一、它们都属于哪一类工具&#xff1f;Selenium、Appium、Playwright、Cypress 等都属于&#xff1a;▶️ 自动化测试框架…

      基于cornerstone3D的dicom影像浏览器 第三十二章 文件夹做pacs服务端,fake-pacs-server

      文章目录 前言一、实现思路二、项目与代码三、dicom浏览器调用1. view2d.vue前言 本系列最后一章,提供一个模拟pacs服务,供访问dicom图像测试。 修改nodejs本地目录做为http服务根目录,提供一个根目录,其中的每个子目录代表一个检查。在dicom浏览器url中带入参数studyId=目…

      【Python 核心概念】深入理解可变与不可变类型

      文章目录一、故事从变量赋值说起二、不可变类型 (Immutable Types)三、可变类型 (Mutable Types)四、一个常见的陷阱&#xff1a;当元组遇到列表五、为什么这个区别如此重要&#xff1f;1. 函数参数的传递2. 字典的键 (Dictionary Keys)3. 函数的默认参数陷阱六、进阶话题与扩展…

      wpf使用webview2显示网页内容(最低兼容.net framework4.5.2)

      wpf使用webview2显示网页内容(最低兼容.net framework4.5.2 一、核心功能与架构混合开发支持‌进程隔离模型‌通信机制‌二、核心优势性能与兼容性‌跨平台部署‌开发效率‌安全机制‌三、适用场景四、开发部署要点WebView2 是微软推出的现代浏览器控件,基于 Chromium 内核的 …