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

这篇具有很好参考价值的文章主要介绍了vue2+three.js实现类似VR、3D全景效果。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

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

效果图:
vue 实现vr,前端,javascript,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>

这里

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

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

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

实在不行就把调试窗口给单独拎出来

代码有很多用不到的地方和需要优化的地方,我是来不及改了,就先这样吧。文章来源地址https://www.toymoban.com/news/detail-613200.html

到了这里,关于vue2+three.js实现类似VR、3D全景效果的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【js&three.js】全景vr看房进阶版

    Scene场景 指包含了所有要渲染和呈现的三维对象、光源、相机以及其他相关元素的环境;场景可以被渲染引擎或图形库加载和处理,以生成最终的图像或动画 常见属性: 常见方法: Geometry  几何体 指的是表示和描述三维对象形状的数据, 描述了对象的形状 常用的Geometry(几

    2024年02月10日
    浏览(47)
  • 微信小程序集成three.js--VR全景项目源码

    小程序集成Three.js,展示不同贴图材质的运用 实现VR全景效果的部分,主要实现步骤如下: 1 创建一个正方体 2加载6个不同面的图片作为正方体的材质 3设置正方体属性 cube.geometry.scale(1,1,-1),即完成了正方体面的反转 4将camera的位置设置在正方体内部,即实现了从内部观察正

    2024年02月11日
    浏览(49)
  • vue 项目使用three.js 实现3D看房效果

    0.前言 该教程能帮助直接写出vue项目的3D看房效果!!! 先上效果图 1.安装依赖 2.vue代码 这里文件名为three.vue 代码非原创,出处 vue3+threejs实现全景看房 (异步加载 BOLLROOM 部件为对原代码的修改) 注意这里的hdr 文件必须要放在assets文件夹中,且要通过import模块的形式导入!

    2024年02月13日
    浏览(55)
  • three.js实现VR看房自由

           在很多看房软件,例如贝壳看房、VR博物馆或者VR展厅等等,为了更加真实的展示产品或者场景的特色,通常会通过一些VR或者全景图的方式,给用户带来沉浸式的体验,给视觉上带来比较震撼的效果,再加上一些动感的音乐,仿佛让人深陷其中,无法自拔。假的,因

    2024年01月18日
    浏览(41)
  • three.js入门篇8 之 实现VR看房

    vue create vr360-vue3 yarn add three code 效果 code 效果

    2024年02月06日
    浏览(38)
  • 使用Pano2VR实现全景图切换和平面图效果

            本文在文章《使用Pano2VR实现背景音乐、放大/缩小、旋转、缩略图和直线/立体/鱼眼模式等》基础上,增加全景图切换和平面图效果;效果如下图(为了可以上传缩小屏幕,属于PC端运行):         1. 运行Pano2VR软件后,打开文章 《使用Pano2VR实现背景音乐、放

    2024年02月06日
    浏览(49)
  • 【案例】VR全景图:效果+源码

    狠人话不多说,直接放视频效果地址 1.视频效果 视频效果地址:点击这里 2.图片效果 该怎么实现? 页面如何布局 页面是否可随意控制显示 1.功能 控制页面显示数量 可放大控制全景图+自动播放 左右按钮控制上一页或下一页(尾页:下一页按钮隐藏,首页:上一页按钮隐藏

    2024年02月12日
    浏览(32)
  • three.js实现3D室内全景看房

    首先我们先搭建一个项目,我选择使用vite来进行项目的搭建,执行命令如下: 这样一个基本的项目就搭建成功了,目录如下所示 然后,下载一下three.js工具,执行如下命令 页面中引入 先搭建一个立体图形,并画出辅助线,如下所示  实现代码如下: 接着,给我们的立体图

    2024年02月12日
    浏览(48)
  • 基于vue3.0实现vr全景编辑器

    随着社会的不断发现,现实生活中有很多时候会使用到全景现实,比如房地产行业vr看房,汽车行业vr看车之类的,全景可视化真实还原了现场的场景,真正做到沉浸式体验。 现在我们基于vue3.0版本开发出了一款沉浸式的编辑器,只需要使用全景相机在现场拍摄全景场景,然

    2024年02月15日
    浏览(45)
  • uniapp中使用photo-sphere-viewer.js实现全景VR图

    最近项目中要求vr功能,可以进行图片的全景查看,在此,用到了vue里的一个实现全景预览的插件:photo-sphere-viewer.js。这些插件,在uniapp中不能直接用。不过uniapp有个组件web-view,可以引入内部或外部的HTML。 首先写一个html,在html中引入三个js文件 在body中放一个div 在js中ne

    2024年02月11日
    浏览(78)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包