赞
踩
效果图:
俩图标是我自己加的前进后退按钮,也是百度了好久,再加上GPT的帮助,才给搞出来。因为需求急,都不看官方文档,百度到一个能跑的demo之后改吧改吧,就先用着了。
下面是代码:
<template> <div> <div id="container" ref="container"></div> </div> </template> <script> import * as THREE from 'three'; import TWEEN from '@tweenjs/tween.js' import { OrbitControls } from "three/examples/jsm/controls/OrbitControls" export default { data () { return { sceneIndex:0, door:null, bigImg: require("../../../assets/555.jpg"), // 图片路径 container: null, // 页面容器 camera: null, // 相机 renderer: null, // 渲染器 scene: null, // 场景 material: null, // 添加材质 texture: null,// 创建纹理贴图 skyBox: null, // 网格 controls: null, // 轨道控制 clock: null, // 轨道更新时间 // 鼠标属性 bMouseDown: false, x: -1, y: -1, isClickCamera: false, // 是否点运动相机 raycaster: null, mouse: null, poiObjects:[], scenesList:[],//场景列表 ImageList:[ '111.jpg', '222.jpg', '333.jpg', '444.jpg', '555.jpg', ],//场景图片了列表 } }, mounted () { this.$nextTick(() => { this.init(); this.animate(); }) }, created () { }, methods: { // 初始化轨道控制 initControls() { this.controls = new OrbitControls(this.camera, this.renderer.domElement); this.controls.target = new THREE.Vector3(0, 0, 0); this.controls.minDistance = 18; // 相机最近 this.controls.maxDistance = 500; // 相机最远 this.controls.autoRotate = false; // 图片自动旋转 this.controls.enableDamping = false; // 使动画循环使用时阻尼或自转 意思是否有惯性 this.controls.enablePan = false; // 是否开启右键拖拽 this.controls.autoRotateSpeed = 0.5; // 阻尼系数 }, init() { // 页面容器 this.container = document.getElementById('container'); // 创建渲染器 this.renderer = new THREE.WebGLRenderer(); this.renderer.setPixelRatio(window.devicePixelRatio); // 设置画布的宽高 this.renderer.setSize(window.innerWidth, window.innerHeight); // 判断容器中子元素的长度判断当前容器元素中是否已经包含了canvas元素,如果已经有了,则删除原来的canvas元素,添加新的canvas元素;如果没有,则直接添加canvas元素。 let childs = this.container.childNodes; if (this.container.childNodes.length > 0) { this.container.removeChild(childs[0]); this.container.appendChild(this.renderer.domElement); } else { this.container.appendChild(this.renderer.domElement); } // 创建场景 this.scene = new THREE.Scene(); // 创建相机 this.camera = new THREE.PerspectiveCamera(80, window.innerWidth / window.innerHeight, 1, 10000); this.camera.position.set(5, 0, 0); this.camera.lookAt(new THREE.Vector3(1, 0, 0)); //让相机指向原点 // 创建轨道控制器 this.initControls(); // 添加材质 this.material = new THREE.MeshBasicMaterial(); // 创建纹理贴图 this.texture = new THREE.TextureLoader().load(this.bigImg); this.material.map = this.texture; // 创建网格对象 this.skyBox = new THREE.Mesh(new THREE.SphereBufferGeometry(100, 100, 100), this.material); this.skyBox.geometry.scale(1, 1, -1); // 显示坐标光线 // var axisHelper = new THREE.AxisHelper(600); // 显示光线(红色代表X轴,绿色代表Y轴,蓝色代表Z轴) // 添加到场景中去 // this.scene.add(axisHelper); this.scene.add(this.skyBox); // 添加一个箭头 // const arrow1 = new THREE.ArrowHelper(new THREE.Vector3(1, 0, 0), new THREE.Vector3(10, 0, 0), 5, 0xff0000); // arrow1.name = 'arrow1'; // this.scene.add(arrow1); // 鼠标事件监听 this.renderer.domElement.addEventListener('pointerdown', this.onMouseDown, false); this.renderer.domElement.addEventListener('pointerup', this.onMouseUp, false); this.renderer.domElement.addEventListener('pointermove', this.onMouseMove, false); // 监听布局变化 window.addEventListener('resize', this.onWindowResize, false); this.createMoreImage(0) }, // 更新相机动画 tweenCamera(position, target) { new TWEEN.Tween(this.camera.position).to({ x: position.x, y: position.y, z: position.z }, 600).easing(TWEEN.Easing.Sinusoidal.InOut).start(); new TWEEN.Tween(this.controls.target).to({ x: target.x, y: target.y, z: target.z }, 600).easing(TWEEN.Easing.Sinusoidal.InOut).start(); }, // 鼠标按下 onMouseDown(event) { event.preventDefault(); // 取消默认事件 console.log("---onMouseDown---"); var raycaster = new THREE.Raycaster(); var mouse = new THREE.Vector2(); mouse.x = (event.clientX / window.innerWidth) * 2 - 1; mouse.y = -(event.clientY / window.innerHeight) * 2 + 1; raycaster.setFromCamera( mouse, this.camera ); var intersects = raycaster.intersectObjects( this.scene.children,true); if(intersects.length>0){ console.log(intersects); let name = intersects[0].object.name if (!name) { return } if (name == '前进') { this.sceneIndex +=1; if (this.sceneIndex > this.ImageList.length - 1) { this.sceneIndex = this.ImageList.length - 1 return } }else if (name == '后退') { this.sceneIndex-- if (this.sceneIndex < 0) { this.sceneIndex = 0 } } this.createMoreImage(this.sceneIndex) this.render.render(this.scene,this.camera) this.camera.position.set(5,0,0) } this.isClickCamera = true; }, // 鼠标放开 onMouseUp(event) { event.preventDefault(); // 取消默认事件 console.log("---onMouseUp---"); }, // 鼠标移动 onMouseMove(event) { event.preventDefault(); // 取消默认事件 console.log("---onMouseMove---"); this.isClickCamera = false; }, onWindowResize() { // 窗口缩放的时候,保证场景也跟着一起缩放 this.camera.aspect = window.innerWidth / window.innerHeight; this.camera.updateProjectionMatrix(); this.renderer.setSize(window.innerWidth, window.innerHeight); }, animate() { requestAnimationFrame(this.animate); this.controls.update(); // 更新轨道控制 TWEEN.update(); this.renderer.render(this.scene, this.camera); }, // 循环创建场景 createMoreImage(index){ let scene = new THREE.Scene(); scene.name = index let texture = new THREE.TextureLoader().load(require('../../../assets/' + this.ImageList[index])); let material = new THREE.MeshBasicMaterial(); material.map = texture; let skyBox = new THREE.Mesh(new THREE.SphereBufferGeometry(100, 100, 100), material); skyBox.geometry.scale(1, 1, -1); scene.add(skyBox) var hotPoints=[ { position:{ x:-98, y:13, z:10 }, detail:{ "title":"前进" } }, { position:{ x:-58, y:-37, z:70 }, detail:{ "title":"后退" } } ]; var pointTexture = new THREE.TextureLoader().load(require('../../../assets/6.png')); var material1 = new THREE.SpriteMaterial( { map: pointTexture,fog: true,color: 0xffffff,} ); for(var i=0;i<hotPoints.length;i++){ var sprite = new THREE.Sprite( material1 ); sprite.scale.set( 10,10,10); sprite.position.set( hotPoints[i].position.x, hotPoints[i].position.y, hotPoints[i].position.z ); sprite.name = hotPoints[i].detail.title sprite.detail = hotPoints[i].detail; sprite.material.depthTest = false; sprite.renderOrder = i; sprite.center = new THREE.Vector2(0.5, 0.5); // 设置锚点为精灵对象中心 this.poiObjects.push(sprite); scene.add( sprite ); } this.scene = scene // 播放相机缓慢移动的动画 function animateCamera(targetPos, targetRot, duration) { var startPos = camera.position.clone(); var startRot = camera.rotation.clone(); var startTime = Date.now(); function animate() { var now = Date.now(); var timeElapsed = now - startTime; var progress = timeElapsed / duration; if (progress >= 1.0) { camera.position.copy(targetPos); camera.rotation.copy(targetRot); return; } var easedProgress = Math.sin(progress * Math.PI / 2); camera.position.lerpVectors(startPos, targetPos, easedProgress); camera.rotation.slerpQuaternions(startRot, targetRot, easedProgress); requestAnimationFrame(animate); } animate(); } }, } } </script>
这里
这里 tween.js 应该是动画库,切换场景动画,或者视角转动动画等,我好像没用上,
其他没啥好说的,我也不咋会,反正能跑起来,有啥不会问GPT吧。
然会这里面还有一个坑就是,要把body和html的margin和padding变成0 ,不然检测不到点击添加的那俩图标,
他好像是根据点击页面的i像素,来换算成坐标的,有padding或者margin就换算的不准确了,我排查了好久。。。。
实在不行就把调试窗口给单独拎出来
代码有很多用不到的地方和需要优化的地方,我是来不及改了,就先这样吧。
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。