VR全景分析.md
9.51 KB
VR 全景分析
最后更新: 2026-02-09 相关文件:
-
src/components/VRViewer/index.vue- VR 全景查看器组件 -
src/api/map.js- 地图数据 API(包含全景图 URL)
技术栈
全景查看器库
Photo Sphere Viewer - 360° 全景查看器
| 库 | 版本 | 用途 |
|---|---|---|
photo-sphere-viewer |
4.8.1 | 全景查看器(旧版本,已弃用) |
@photo-sphere-viewer/core |
5.7.3 | 全景查看器核心(新版本) |
@photo-sphere-viewer/markers-plugin |
5.7.3 | 标记点插件 |
@photo-sphere-viewer/virtual-tour-plugin |
5.7.3 | 虚拟漫游插件 |
@photo-sphere-viewer/gallery-plugin |
5.7.3 | 图库插件 |
@photo-sphere-viewer/gyroscope-plugin |
5.7.3 | 陀螺仪插件 |
@photo-sphere-viewer/stereo-plugin |
5.7.3 | 立体插件(VR 眼镜) |
⚠️ 注意: 项目中同时存在 4.8.1 和 5.7.3 两个版本,建议统一使用 5.x 版本。
核心功能
1. 全景图查看
功能:
- ✅ 360° 全景浏览
- ✅ 缩放控制
- ✅ 自动旋转
- ✅ 陀螺仪控制(移动设备)
初始化:
import { Viewer } from '@photo-sphere-viewer/core';
const viewer = new Viewer({
container: document.querySelector('#viewer'),
panorama: '/path/to/panorama.jpg',
defaultZoomLvl: 0,
fisheye: true,
loadingTxt: '加载中...',
});
2. 标记点 (Markers)
插件: @photo-sphere-viewer/markers-plugin
功能:
- ✅ 添加标记点
- ✅ 标记点点击事件
- ✅ 自定义标记点样式
- ✅ 多边形标记点
使用示例:
import { MarkersPlugin } from '@photo-sphere-viewer/markers-plugin';
const markersPlugin = new MarkersPlugin();
viewer.setPlugin(markersPlugin);
// 添加标记点
viewer.addMarker({
id: 'marker1',
position: { yaw: 0, pitch: 0 },
html: '<div class="marker">标记点</div>',
scale: [1, 1],
});
// 监听标记点点击
markersPlugin.addEventListener('select-marker', ({ marker }) => {
console.log('点击标记点:', marker.id);
});
3. 虚拟漫游 (Virtual Tour)
插件: @photo-sphere-viewer/virtual-tour-plugin
功能:
- ✅ 多场景切换
- ✅ 场景之间的链接
- ✅ 箭头指示器
- ✅ 自动路径播放
使用示例:
import { VirtualTourPlugin } from '@photo-sphere-viewer/virtual-tour-plugin';
const virtualTour = new VirtualTourPlugin();
viewer.setPlugin(virtualTour);
// 设置节点
virtualTour.setNodes([
{
id: '1',
panorama: '/path/to/panorama1.jpg',
links: [
{
name: '场景 2',
nodeId: '2',
position: { yaw: -300, pitch: 0 },
arrowStyle: {
color: '#AEEEEE',
hoverColor: 0xaa5500,
outlineColor: 0x000000,
scale: [1, 1],
}
},
],
markers: [...],
},
{
id: '2',
panorama: '/path/to/panorama2.jpg',
links: [...],
markers: [...],
},
]);
// 切换场景
virtualTour.setCurrentNode('2');
4. 图库 (Gallery)
插件: @photo-sphere-viewer/gallery-plugin
功能:
- ✅ 全景图列表
- ✅ 缩略图导航
- ✅ 自动切换
使用示例:
import { GalleryPlugin } from '@photo-sphere-viewer/gallery-plugin';
const gallery = new GalleryPlugin({
thumbnailSize: {
width: 100,
height: 100,
},
});
viewer.setPlugin(gallery);
// 设置图库
gallery.setItems([
{
id: '1',
panorama: '/path/to/panorama1.jpg',
name: '场景 1',
thumbnail: '/path/to/thumb1.jpg',
},
{
id: '2',
panorama: '/path/to/panorama2.jpg',
name: '场景 2',
thumbnail: '/path/to/thumb2.jpg',
},
]);
5. 陀螺仪 (Gyroscope)
插件: @photo-sphere-viewer/gyroscope-plugin
功能:
- ✅ 设备方向控制
- ✅ 移动设备支持
- ✅ VR 眼镜模式
使用示例:
import { GyroscopePlugin } from '@photo-sphere-viewer/gyroscope-plugin';
const gyroscope = new GyroscopePlugin();
viewer.setPlugin(gyroscope);
// 启用陀螺仪
gyroscope.toggle();
6. 立体模式 (Stereo)
插件: @photo-sphere-viewer/stereo-plugin
功能:
- ✅ VR 眼镜模式
- ✅ 立体视图
使用示例:
import { StereoPlugin } from '@photo-sphere-viewer/stereo-plugin';
const stereo = new StereoPlugin();
viewer.setPlugin(stereo);
// 启用立体模式
stereo.toggle();
组件使用
VRViewer 组件
路径: src/components/VRViewer/index.vue
Props:
{
show: Boolean // 控制显示/隐藏
}
使用示例:
<template>
<VRViewer
v-model:show="showVR"
:panorama="panoramaUrl"
:markers="markers"
@marker-click="handleMarkerClick"
/>
</template>
<script setup>
import VRViewer from '@components/VRViewer/index.vue';
import { ref } from 'vue';
const showVR = ref(false);
const panoramaUrl = ref('/vr/panorama.jpg');
const markers = ref([
{
id: 'marker1',
position: { yaw: 0, pitch: 0 },
html: '<div class="marker">标记点</div>',
}
]);
const handleMarkerClick = (marker) => {
console.log('点击标记点:', marker);
};
// 打开 VR
const openVR = () => {
showVR.value = true;
};
</script>
全景图格式
支持的格式
- ✅ JPEG (推荐)
- ✅ PNG
- ✅ WebP (推荐,体积更小)
拍摄要求
等距柱状投影 (Equirectangular Projection):
- 宽高比: 2:1
- 分辨率: 至少 4096 x 2048
- 格式: 等距柱状投影
文件大小建议: | 分辨率 | 文件大小 | |--------|---------| | 2048 x 1024 | < 2 MB | | 4096 x 2048 | 2-5 MB | | 8192 x 4096 | 5-15 MB |
图片优化
压缩建议:
- JPEG 质量: 80-90%
- WebP 质量: 80-90%
- 使用渐进式 JPEG
工具推荐:
- Adobe Lightroom
- Photoshop
- 在线压缩工具
性能优化
1. 懒加载
// 仅在需要时加载全景图
const loadPanorama = async (url) => {
const viewer = new Viewer({
container: document.querySelector('#viewer'),
panorama: url,
loadingTxt: '加载中...',
});
await viewer.ready();
return viewer;
};
2. 缩略图
// 先加载缩略图,再加载高清图
const viewer = new Viewer({
container: document.querySelector('#viewer'),
panorama: thumbnailUrl, // 缩略图
requestFullscreen: true,
});
// 后台加载高清图
loadFullPanorama(fullUrl).then((fullUrl) => {
viewer.setPanorama(fullUrl);
});
3. 缓存策略
// 缓存已加载的全景图
const panoramaCache = new Map();
export const getCachedPanorama = (url) => {
if (panoramaCache.has(url)) {
return Promise.resolve(panoramaCache.get(url));
}
return new Promise((resolve) => {
const img = new Image();
img.onload = () => {
panoramaCache.set(url, url);
resolve(url);
};
img.src = url;
});
};
4. 资源释放
// 组件卸载时释放资源
onUnmounted(() => {
if (viewer.value) {
viewer.value.destroy();
viewer.value = null;
}
});
已知问题
1. 版本冲突
问题: 同时使用 4.x 和 5.x 版本
解决方案: 统一使用 5.x 版本
// ❌ 错误
import { Viewer } from 'photo-sphere-viewer'; // 4.x
import { Viewer } from '@photo-sphere-viewer/core'; // 5.x
// ✅ 正确
import { Viewer } from '@photo-sphere-viewer/core'; // 仅使用 5.x
2. jQuery 依赖
问题: 组件中使用 jQuery
解决方案: 逐步迁移到 Vue 原生 API
// ❌ 错误
$('.psv-zoom-button').css('display', '');
// ✅ 正确
document.querySelector('.psv-zoom-button').style.display = '';
3. 内存泄漏
问题: 未正确销毁查看器实例
解决方案: 组件卸载时销毁
onUnmounted(() => {
if (viewer) {
viewer.destroy();
}
});
4. 移动端性能
问题: 高分辨率全景图加载慢
解决方案:
- 使用 WebP 格式
- 降低分辨率
- 使用缩略图预加载
最佳实践
1. 组件使用
<!-- ✅ 推荐:使用 v-model -->
<VRViewer v-model:show="showVR" />
<!-- ❌ 不推荐:手动控制 -->
<VRViewer :show="showVR" @close="showVR = false" />
2. 全景图路径
// ✅ 推荐:使用别名
const panoramaUrl = ref('@images/vr/panorama.jpg');
// ❌ 不推荐:使用相对路径
const panoramaUrl = ref('../../images/vr/panorama.jpg');
3. 标记点定义
// ✅ 推荐:使用配置对象
const markerConfig = {
id: 'marker1',
position: { yaw: 0, pitch: 0 },
html: '<div class="marker">标记点</div>',
};
// ❌ 不推荐:内联定义
viewer.addMarker({
id: 'marker1',
position: { yaw: 0, pitch: 0 },
html: '<div class="marker">标记点</div>',
});
调试技巧
1. 查看查看器状态
// 在控制台查看查看器状态
console.log('查看器状态:', {
position: viewer.getPosition(),
zoom: viewer.getZoomLevel(),
size: viewer.getSize(),
});
2. 监听事件
// 监听所有事件
viewer.addEventListener('ready', () => console.log('就绪'));
viewer.addEventListener('position-updated', (e) => console.log('位置更新:', e.position));
viewer.addEventListener('zoom-updated', (e) => console.log('缩放更新:', e.zoomLevel));
3. 手动控制
// 手动旋转
viewer.animate({
yaw: 180,
pitch: 0,
zoom: 0,
speed: 1000,
});
// 手动缩放
viewer.zoom(1);