实战篇:(四)Vue2 + Three.js 创建可交互的360度全景视图,可控制旋转、缩放完整代码

Vue2 + Three.js 创建可交互的360度全景视图,可控制旋转、缩放

引言

在现代网页开发中,三维图形技术已经成为提升用户体验的重要工具。本文将展示如何使用 Three.js 创建一个简单的可交互360度全景视图。通过这一项目,你将能够学习到基本的场景设置、相机控制以及用户交互的实现方式。

效果展示

环境准备

首先,你需要在项目中引入 Three.js。可以通过 npm 安装:

bash 复制代码
npm install three

确保你的项目结构中有一个名为 images 的文件夹,并放入一张全景图像(如 001.jpg),以便后续使用。

代码示例

下面是实现可交互360度全景视图的 Vue.js 组件代码:

js 复制代码
<template>
  <div class="c-width c-height" id="containerVr"></div>
</template>

<script>
import * as THREE from 'three';
import PANO0001 from './images/001.jpg';

export default {
  name: 'containerVr',
  data() {
      return {
          scene: null,
          camera: null,
          renderer: null,
      };
  },
  mounted() {
      this.init();
  },
  methods: {
      init(img) {
          img = img ? img : PANO0001;
          const containerVr = document.getElementById('containerVr');
          containerVr.innerHTML = '';
          
          // 初始化用户交互变量
          let isUserInteracting = false,
              onPointerDownMouseX = 0, onPointerDownMouseY = 0,
              lon = 0, onPointerDownLon = 0,
              lat = 0, onPointerDownLat = 0,
              phi = 0, theta = 0;

          // 创建相机对象
          const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 1, 1100);
          
          // 创建场景对象
          const scene = new THREE.Scene();
          
          // 创建球体几何体,表示全景图的表面
          const geometry = new THREE.SphereGeometry(500, 60, 40);
          geometry.scale(-1, 1, 1);
          
          // 加载并设置全景图纹理
          const texture = new THREE.TextureLoader().load(img);
          texture.colorSpace = THREE.SRGBColorSpace;
          const material = new THREE.MeshBasicMaterial({ map: texture });
          
          // 创建网格对象,将几何体和材质结合
          const mesh = new THREE.Mesh(geometry, material);
          scene.add(mesh);
          
          // 创建渲染器并设置参数
          const renderer = new THREE.WebGLRenderer();
          renderer.setSize(window.innerWidth, window.innerHeight);
          renderer.setPixelRatio(window.devicePixelRatio);
          
          // 将渲染器的DOM元素添加到容器中
          containerVr.appendChild(renderer.domElement);
          containerVr.style.touchAction = 'none';
          
          // 添加事件监听器以处理用户交互
          containerVr.addEventListener('pointerdown', onPointerDown);
          document.addEventListener('wheel', onDocumentMouseWheel);
          
          // 窗口大小调整事件
          window.addEventListener('resize', onWindowResize);
          function onWindowResize() {
              camera.aspect = window.innerWidth / window.innerHeight;
              camera.updateProjectionMatrix();
              renderer.setSize(window.innerWidth, window.innerHeight);
          }

          // Pointer Down事件处理
          function onPointerDown(event) {
              if (event.isPrimary === false) return;
              isUserInteracting = true;
              onPointerDownMouseX = event.clientX;
              onPointerDownMouseY = event.clientY;
              onPointerDownLon = lon;
              onPointerDownLat = lat;
              document.addEventListener('pointermove', onPointerMove);
              document.addEventListener('pointerup', onPointerUp);
          }

          // Pointer Move事件处理
          function onPointerMove(event) {
              if (event.isPrimary === false) return;
              lon = (onPointerDownMouseX - event.clientX) * 0.1 + onPointerDownLon; 
              lat = (event.clientY - onPointerDownMouseY) * 0.1 + onPointerDownLat;
          }

          // Pointer Up事件处理
          function onPointerUp() {
              if (event.isPrimary === false) return;
              isUserInteracting = false;
              document.removeEventListener('pointermove', onPointerMove);
              document.removeEventListener('pointerup', onPointerUp);
          }

          // 滚轮事件处理
          function onDocumentMouseWheel(event) {
              if (event.toElement.getAttribute('data-engine') && event.toElement.getAttribute('data-engine').indexOf('three.js') > -1) {
                  const fov = camera.fov + event.deltaY * 0.05; 
                  camera.fov = THREE.MathUtils.clamp(fov, 10, 75); 
                  camera.updateProjectionMatrix(); 
              }
          }

          // 动画循环
          function animate() {
              requestAnimationFrame(animate);
              update();
          }

          // 更新函数,处理相机位置和渲染
          function update() {
              if (isUserInteracting === false) {
                  lon += 0.02; 
              }
              lat = Math.max(-85, Math.min(85, lat));
              phi = THREE.MathUtils.degToRad(90 - lat);
              theta = THREE.MathUtils.degToRad(lon);
              const x = 500 * Math.sin(phi) * Math.cos(theta);
              const y = 500 * Math.cos(phi);
              const z = 500 * Math.sin(phi) * Math.sin(theta);
              camera.lookAt(x, y, z); 
              renderer.render(scene, camera); 
          }
          animate(); 
      },
      // 设置图像的方法
      setImg(url) {
          let loader = new THREE.TextureLoader(); 
          let texture = loader.load(url); 
          let material = new THREE.MeshBasicMaterial({
              map: texture, 
              side: THREE.DoubleSide 
          });
          return material; 
      },
  }
}
</script>

<style scoped>
#containerVr {
  width: 100% !important; 
  flex: 1 !important; 
}
#containerVr >>> canvas {
  max-width: 100%; 
  max-height: 100%; 
}
</style>

代码解析

  • 组件结构 :该组件使用 Vue.js 的 <template><script><style> 标签组织代码。
  • 初始化方法 :在 mounted 钩子中调用 init 方法,初始化 Three.js 的场景、相机和渲染器。
  • 用户交互:实现了鼠标按下、移动和滚动事件,用户可以通过拖动鼠标来旋转视图。
  • 自适应窗口:通过监听窗口大小变化事件,动态更新相机和渲染器的尺寸。

总结

通过本文,你可以学习如何使用 Three.js 创建一个基础的360度全景视图。这种技术可以广泛应用于虚拟现实、在线展示以及游戏开发等多个领域。希望这篇文章对你理解 Three.js 和创建互动场景有所帮助。

进一步学习

通过这种方式,读者不仅可以理解代码的具体实现,还能了解到如何在实际项目中应用这些技术。希望这个结构能帮助你更好地撰写博客!如果你有其他想法或需要进一步的帮助,请告诉我。

相关推荐
We་ct3 小时前
深度剖析浏览器跨域问题
开发语言·前端·浏览器·跨域·cors·同源·浏览器跨域
skywalk81633 小时前
在考虑双轨制,即在中文语法的基础上,加上数学公式的支持,这样像很多计算将更加简单方便,就像现在的小学数学课本里面一样,比如:定x=2*x + 1
开发语言
小书房3 小时前
Kotlin的by
android·开发语言·kotlin·委托·by
就叫飞六吧3 小时前
QT写一个桌面程序exe并动态打包基本流程(c++)
开发语言·c++
threelab3 小时前
Three.js 代码云效果 | 三维可视化 / AI 提示词
开发语言·javascript·人工智能
V搜xhliang02463 小时前
OpenClaw科研全场景用法:从文献到实验室的完整自动化方案
运维·开发语言·人工智能·python·算法·microsoft·自动化
kaikaile19954 小时前
风、浪、流环境模型的船舶三自由度(纵荡、横荡、艏摇)运动仿真MATLAB
开发语言·人工智能·matlab
fish_xk4 小时前
map和set
java·开发语言
李崧正4 小时前
Java技术分享:Lambda表达式与函数式编程
java·开发语言·python
老了,不知天命4 小时前
鳶尾花項目JAVA
java·开发语言·机器学习