当前位置: 首页 > news >正文

three初体验

three我的理解就是:先创建一个 鱼缸(scene),需要什么东西,就往鱼缸里加

scene场景
场景里面有背景,就加 this.scene.background
要添加模型,this.scene.add(模型)
要有标记点,就创建一个精灵标记点 this.scene.add(精灵标记)
等等

重点是 initThreeJS() 函数和 animate()函数


<div ref="canvasContainer" id="canvas-container"></div>

引入three和tween

import * as THREE from 'three'
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
import TWEEN from '@tweenjs/tween.js'
// data: 
camera: null, // 相机
scene: null, // 场景
renderer: null, // 渲染器
gltf: null, // GLTF模型
controls: null, // 轨道控制器
mounted() {// 绑定 animate 方法到当前实例,防止 this 丢失this.animate = this.animate.bind(this)// 初始化Three.js场景this.initThreeJS()
},
// 在页面销毁前,删除所有的三维实例和注册的..
beforeDestroy() {// 清理Three.js资源, 包括渲染器、场景和模型, 标记, 轨迹等if (this.renderer) {if (this.renderer.forceContextLoss) {this.renderer.forceContextLoss()}this.renderer.domElement = nullthis.renderer = null}if (this.scene) {this.scene.clear()this.scene = null}if (this.gltf) {if (this.gltf.scene && this.scene) {this.scene.remove(this.gltf.scene)}this.gltf = null}this.stopAnimate = true // 停止动画window.removeEventListener('resize', this.onWindowResize)
},
// methods:
initThreeJS() {// 初始化场景、相机、渲染器等this.scene = new THREE.Scene()this.camera = new THREE.PerspectiveCamera(50,window.innerWidth / window.innerHeight,0.1,100000000)this.renderer = new THREE.WebGLRenderer({ antialias: true })this.renderer.setSize(window.innerWidth, window.innerHeight)this.$el.querySelector('#canvas-container').appendChild(this.renderer.domElement)// 添加光源和环境const ambientLight = new THREE.AmbientLight(0xffffff, 0.5)this.scene.add(ambientLight)const directionalLight1 = new THREE.DirectionalLight(0xffffff, 10)directionalLight1.position.set(10, 20, 5)this.scene.add(directionalLight1)const directionalLight2 = new THREE.DirectionalLight(0xffffff, 10)directionalLight2.position.set(-10, -20, -5)this.scene.add(directionalLight2)// 添加天空背景图const textureLoader = new THREE.TextureLoader()const texture = textureLoader.load('本地天空图片')// 设置纹理this.scene.background = texture// 初始化轨道控制器this.controls = new OrbitControls(this.camera, this.renderer.domElement)this.controls.minPolarAngle = 0this.controls.maxPolarAngle = Math.PI / 2this.controls.maxDistance = 1000// 加载模型const loader = new GLTFLoader()// let model = nullloader.load('本地模型 xxx.glb',(gltf) => {this.gltf = gltfthis.scene.add(gltf.scene)this.animate()this.loading = false},undefined,(error) => {console.error(`Error loading model: ${error}`)})// 设置初始相机位置this.camera.position.set(0, 40, 100)this.controls.target.set(20, 10, 5)this.controls.update()this.stopAnimate = false // 启动动画// 监听窗口大小变化window.addEventListener('resize', this.onWindowResize, false)
},
// 添加人员用户标记(做沿轨迹动画)
addUserMarker() {const spriteMap = new THREE.TextureLoader().load('http://172.16.9.115:5304/images/user.svg') // 人物标记图片const spriteMaterial = new THREE.SpriteMaterial({ map: spriteMap })this.userMarker = new THREE.Sprite(spriteMaterial)this.scene.add(this.userMarker)const start = this.pathPoints[0]// y 轴偏移 高度 + 1this.userMarker.position.set(start.x, start.y + 6, start.z)this.userMarker.scale.set(9, 12, 1)
},
onWindowResize() {this.camera.aspect = window.innerWidth / window.innerHeightthis.camera.updateProjectionMatrix()this.renderer.setSize(window.innerWidth, window.innerHeight)
},
// 要不停的调用
animate() {if (this.stopAnimate) return // 如果停止动画,则直接返回requestAnimationFrame(this.animate)TWEEN.update()this.controls.update()// 以下逻辑(在场景中创建一个平铺在地面的轨迹路径,创建一个人员精灵标记,// 然后让精灵标记沿路径做循环动画)。不需要可以不用管// 轨迹函数在我另一篇博客中// === 新增:让 userMarker 沿路径循环运动 ===// if (this.userMarker && this.curve) {// 	this.userT +=// 		(this.userSpeed * this.clock.getDelta()) / this.curve.getLength()// 	if (this.userT > 1) this.userT = 0// 	const pos = this.curve.getPointAt(this.userT)// 	this.userMarker.position.set(pos.x, pos.y + 6, pos.z)// 	// 让精灵朝向运动方向// 	const tangent = this.curve.getTangentAt(this.userT)// 	// const axis = new THREE.Vector3(0, 1, 0)// 	const angle = Math.atan2(tangent.x, tangent.z)// 	this.userMarker.rotation.set(0, angle, 0)// }this.renderer.render(this.scene, this.camera)
},
http://www.lryc.cn/news/592476.html

相关文章:

  • 【基座模型】Qwen3报告总结
  • OpenTelemetry学习笔记(四):OpenTelemetry 语义约定,即字段映射(1)
  • 二、Dify 版本升级教程(LInux-openeuler)
  • 软件维护全维度解析:从修复到进化的生命周期管理
  • linux制作镜像、压缩镜像、烧录的方法
  • iOS 数据持久化
  • iOS 文件深度调试实战 查看用户文件 App 沙盒 系统文件与日志全指南
  • SpringAI核心特性与Prompt工程
  • SQLite 数据库字段类型-详细说明,数据类型详细说明。
  • VMware安装Win10教程(附安装包)虚拟机下载详细安装图文教程
  • 小程序常用api
  • PDF 拆分合并PDFSam:开源免费 多文件合并 + 按页码拆分 本地处理
  • 20250718-2-Kubernetes 应用程序生命周期管理-Pod对象:基本概念(豌豆荚)_笔记
  • Fiori 初学记录 官网 https://sapui5.hana.ondemand.com/ Samples 练习记录
  • springCloud -- 微服务01
  • 信息检索革命:Perplexica+cpolar打造你的专属智能搜索中枢
  • [simdjson] 填充字符串 | `document` 对象 | on-demand 模式
  • AI(day10)模块化编程概念(模块、包、导入)及常见系统模块总结和第三方模块管理
  • 全球天气预报5天(经纬度版)免费API接口教程
  • JavaScript进阶篇——第九章 异常、this 与性能优化全解(终)
  • Agentic AI引领人力资源新范式:易路的技术进化与行业实践
  • Proto文件从入门到精通——现代分布式系统通信的基石(含实战案例)
  • IDEA插件离线安装
  • 手撕Spring底层系列之:Bean的生命周期
  • Diffusion-VLA 中的 Reasoning Token 注入机制解析:语言推理如何控制扩散模型?
  • 51c视觉~合集13
  • 第三章-提示词-初级:一文带你入门提示词工程,开启AI高效交互之旅(11/36)
  • ARCS系统机器视觉实战(直播回放)
  • TapData 出席 2025 MongoDB 用户大会新加坡站,分享构建实时统一数据平台最佳实践
  • Vue3 中使用 Element Plus 实现自定义按钮的 ElNotification 提示框