vue实现全景图
使用Three.js实现全景图
在Vue项目中集成Three.js可以高效实现全景图展示。需要安装Three.js依赖:
npm install three
创建全景图组件:
<template>
<div ref="container" class="panorama-container"></div>
</template>
<script>
import * as THREE from 'three';
export default {
mounted() {
this.initScene();
this.loadPanorama();
window.addEventListener('resize', this.onWindowResize);
},
methods: {
initScene() {
this.scene = new THREE.Scene();
this.camera = new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 0.1, 1000);
this.renderer = new THREE.WebGLRenderer();
this.renderer.setSize(window.innerWidth, window.innerHeight);
this.$refs.container.appendChild(this.renderer.domElement);
},
loadPanorama() {
const textureLoader = new THREE.TextureLoader();
textureLoader.load('panorama.jpg', texture => {
const geometry = new THREE.SphereGeometry(500, 60, 40);
geometry.scale(-1, 1, 1);
const material = new THREE.MeshBasicMaterial({ map: texture });
const sphere = new THREE.Mesh(geometry, material);
this.scene.add(sphere);
this.animate();
});
},
animate() {
requestAnimationFrame(this.animate);
this.renderer.render(this.scene, this.camera);
},
onWindowResize() {
this.camera.aspect = window.innerWidth / window.innerHeight;
this.camera.updateProjectionMatrix();
this.renderer.setSize(window.innerWidth, window.innerHeight);
}
},
beforeDestroy() {
window.removeEventListener('resize', this.onWindowResize);
}
}
</script>
<style>
.panorama-container {
width: 100%;
height: 100vh;
}
</style>
使用Photo Sphere Viewer库
Photo Sphere Viewer是专门用于全景图展示的库,使用更简单:
安装依赖:
npm install photo-sphere-viewer
组件实现:
<template>
<div ref="viewer" class="panorama-viewer"></div>
</template>
<script>
import { Viewer } from 'photo-sphere-viewer';
import 'photo-sphere-viewer/dist/photo-sphere-viewer.css';
export default {
props: {
src: {
type: String,
required: true
}
},
mounted() {
this.viewer = new Viewer({
container: this.$refs.viewer,
panorama: this.src,
size: {
width: '100%',
height: '100vh'
}
});
},
beforeDestroy() {
if (this.viewer) {
this.viewer.destroy();
}
}
}
</script>
移动端适配方案
针对移动设备需要添加陀螺仪控制:
import DeviceOrientationControls from 'three-device-orientation';
// 在initScene方法中添加
this.controls = new DeviceOrientationControls(this.camera);
this.controls.connect();
// 在animate方法中更新
this.controls.update();
性能优化技巧
使用低分辨率预览图快速加载:
textureLoader.load('panorama-lowres.jpg', lowResTexture => {
const material = new THREE.MeshBasicMaterial({ map: lowResTexture });
// 加载高清图后替换
textureLoader.load('panorama-hires.jpg', hiResTexture => {
material.map = hiResTexture;
material.needsUpdate = true;
});
});
添加加载进度指示器:
const manager = new THREE.LoadingManager();
manager.onProgress = (url, loaded, total) => {
console.log(`加载进度: ${loaded}/${total}`);
};
const textureLoader = new THREE.TextureLoader(manager);
热点标记实现
在全景图中添加交互热点:
const hotspotGeometry = new THREE.SphereGeometry(1, 16, 16);
const hotspotMaterial = new THREE.MeshBasicMaterial({ color: 0xff0000 });
const hotspot = new THREE.Mesh(hotspotGeometry, hotspotMaterial);
hotspot.position.set(0, 0, -10);
this.scene.add(hotspot);
// 添加射线检测
this.raycaster = new THREE.Raycaster();
this.mouse = new THREE.Vector2();
window.addEventListener('click', event => {
this.mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
this.mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
this.raycaster.setFromCamera(this.mouse, this.camera);
const intersects = this.raycaster.intersectObjects([hotspot]);
if (intersects.length > 0) {
console.log('热点被点击');
}
});






