当前位置:   article > 正文

vue2+three.js实现类似VR、3D全景效果_vue步进式全景漫游

vue步进式全景漫游

vue2+three.js实现类似VR、3D全景效果

效果图:
在这里插入图片描述
俩图标是我自己加的前进后退按钮,也是百度了好久,再加上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>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270
  • 271
  • 272
  • 273
  • 274
  • 275
  • 276
  • 277
  • 278
  • 279
  • 280
  • 281
  • 282
  • 283

这里

这里 tween.js 应该是动画库,切换场景动画,或者视角转动动画等,我好像没用上,

其他没啥好说的,我也不咋会,反正能跑起来,有啥不会问GPT吧。

然会这里面还有一个坑就是,要把body和html的margin和padding变成0 ,不然检测不到点击添加的那俩图标,
他好像是根据点击页面的i像素,来换算成坐标的,有padding或者margin就换算的不准确了,我排查了好久。。。。

实在不行就把调试窗口给单独拎出来
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

代码有很多用不到的地方和需要优化的地方,我是来不及改了,就先这样吧。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Cpp五条/article/detail/121649
推荐阅读
相关标签
  

闽ICP备14008679号