Vue使用photo-sphere-viewer360°×180°全景插件模拟VR看房、房间切换和自定义标注
Vue使用photo-sphere-viewer360°×180°全景插件模拟VR看房、房间切换photo-sphere-viewer下载插件使用常用参数Markers插件使用完整代码推荐阅读Vue源码学习目录你越是认真生活,你的生活就会越美好——弗兰克·劳埃德·莱特《人生果实》经典语录负责的项目想要实现链接的效果,类似VR看房,支持720°任意旋转,支持自定义添加标注,支持切换场景等功能前端组长
Vue使用photo-sphere-viewer360°×180°全景插件模拟VR看房、房间切换和自定义标注
你越是认真生活,你的生活就会越美好
——弗兰克·劳埃德·莱特
《人生果实》经典语录
负责的项目想要实现链接的效果,类似VR看房,支持720°任意旋转
,支持自定义添加标注
,支持切换场景
等功能
前端组长提供了掘金的麦七写的一篇博客作为参考
博客里使用Markers插件
的代码在本地报错,且不完全满足我想要的效果,所以到photo-sphere-viewer官网上看了下,功能确实强大,这里基于掘金的麦七写的博客
记录下我用到的内容
photo-sphere-viewer
photo-sphere-viewer插件
基于three.js
和uEvent 2
360°×180°全景插件photo-sphere-viewer和他的插件(这里只用到标记插件Markers
)
下载插件
使用npm或yarn下载安装
npm install photo-sphere-viewer
yarn add photo-sphere-viewer
文章使用的版本"photo-sphere-viewer": "^4.3.0"
,
使用
<template>
<div id="viewer"></div>
</template>
<script>
import {Viewer} from 'photo-sphere-viewer'
import 'photo-sphere-viewer/dist/photo-sphere-viewer.css'
export default {
data(){
return{
viewer:'',
imgurl1:`https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/6df92ba39aa94aec889582df60d3d0d0~tplv-k3u1fbpfcp-watermark.awebp`,
}
},
mounted(){
this.viewer = new Viewer({
container:document.querySelector('#viewer'),
panorama:this.imgurl1,
size:{
width: '100vw',
height: '50vh',
},
});
}
}
</script>
常用参数
container
(必需的)
类型:HTMLElement | string 包含全景图或元素标识符的HTML元素。
container: document.querySelector('.viewer')
// 或者
container: 'viewer' // will target [id="viewer"]
panorama
(必需的)
类型: string | string[] | object 全景图像的路径
。
对于等角的全景图,它必须是单个字符串(我文章使用的就是720°全景图);
对于立方体贴图,它必须是数组或对象(对应六个面)。
// Equirectangular panorama :
panorama: 'path/to/panorama.jpg'
// Cubemap as array (order is important) :
panorama: [
'path/to/left.jpg', 'path/to/front.jpg',
'path/to/right.jpg', 'path/to/back.jpg',
'path/to/top.jpg', 'path/to/bottom.jpg',
]
// Cubemap as object :
panorama: {
left: 'path/to/left.jpg', front: 'path/to/front.jpg',
right: 'path/to/right.jpg', back: 'path/to/back.jpg',
top: 'path/to/top.jpg', bottom: 'path/to/bottom.jpg',
}
plugins
类型: array 启用的插件列表。(如后面会用到的标记插件marker)
markers:切换标记
markersList:显示标记列表
gyroscope:陀螺仪切换
stereo:切换立体声视图(VR)
caption
类型: string;导航栏中显示的文本。如果导航栏被禁用,它将一直显示,但没有按钮。允许使用HTML。
size
类型: { width: integer, height: integer };最终大小(如果为全景图容器)。默认情况下,container使用的大小,并在调整窗口大小时遵循。
navbar
导航栏的配置。
autorotate :切换自动旋转
zoomOut :放大
zoomRange :缩放滑块
zoomIn :缩小
zoom:zoomOut+ zoomRange+zoomIn
download :下载源图像
caption :标题
fullscreen :切换全屏视图
自定义导航栏按钮:
navbar: [
{
id: 'my-button',//按钮的唯一标识符,在使用该navbar.getButton()方法时很有用
content: 'Custom',//必需的,按钮内容
title: 'Hello world',//鼠标悬停在按钮上时显示工具提示
className: 'custom-button',//CSS类已添加到按钮
onClick: () => {
alert('Hello from custom button');//必需的,单击按钮时调用的函数
}
//disabled:false,最初禁用该按钮
//hidden:false,最初隐藏按钮
},
]
更多参数参考官网
Markers插件
官方插件(在左侧菜单中列出)可在目录photo-sphere-viewer
内的主软件包中找到dist/plugins
。一些插件还具有其他CSS文件。
import MarkersPlugin from 'photo-sphere-viewer/dist/plugins/markers'
import 'photo-sphere-viewer/dist/plugins/markers.css';
按参考的文章导入 发现获取不到 MarkersPlugin
在node_modules\photo-sphere-viewer\dist\plugins\markers.js
文件里看了源码后发现
源码中有一行代码导出
exports.MarkersPlugin = MarkersPlugin;
导入改为下面的代码 可以正常获取到MarkersPlugin
import { MarkersPlugin } from 'photo-sphere-viewer/dist/plugins/markers'
import 'photo-sphere-viewer/dist/plugins/markers.css'
使用
所有插件均包含一个JavaScript类,该类必须提供给plugins数组
。一些插件还将采用嵌套数组中提供的配置对象。
this.viewer = new Viewer({
container:document.querySelector('#viewer'),
panorama:this.imgurl1,
size:{
width: '100vw',
height: '50vh',
},
plugins: [
[MarkersPlugin, {
markers: [
{
id:'circle',
tooltip:'A circle of radius 30',
circle:30,
svgStyle : {
fill:'rgba(255,255,0,0.3)',
stroke:'yellow',
strokeWidth:'2px',
},
longitude: -1.5,
latitude: -0.28,
anchor: 'center right',
}
],
}],
],
});
初始化之后,可以使用getPlugin方法
获得插件实例,从而允许在插件上调用方法并订阅事件。
const markersPlugin = this.viewer.getPlugin(MarkersPlugin);
markersPlugin.on('something', () => {
/* ... */
});
点击查看更多标记插件的参数方法
标注效果如下
完整代码
下面的代码 更多是为了测试即将要开发的功能能否实现,到时开发完再贴一下最终效果图
下面代码的功能如下
全景图720度旋转
点击时添加自定义标注
,标注会随机配置点击事件随机切换全景图
- 标注内容通过
html自定义
- 标注存在localStorage里(没有区分是哪张全景图的)
<template>
<div class="demo-container">
测试
<div id="viewer"></div>
<ul class="item-container">
<li
v-for="(item, index) in itemArr"
:key="index"
@click="setViewer(item.img)"
>
{{`全景图${index+1}`}}
</li>
</ul>
</div>
</template>
<script>
import { Viewer } from 'photo-sphere-viewer'
import 'photo-sphere-viewer/dist/photo-sphere-viewer.css'
import { MarkersPlugin } from 'photo-sphere-viewer/dist/plugins/markers'
import 'photo-sphere-viewer/dist/plugins/markers.css'
export default {
name: 'demo',
data() {
return {
viewer: '',
markersPlugin: '',
itemArr: [
{
// img: require('@/assets/imgs/demo/demo1.jpeg'),
img: 'https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/0ebbea0343bf44d2aabab3dc58aa4c3a~tplv-k3u1fbpfcp-watermark.awebp'
},
{
img: 'https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/6df92ba39aa94aec889582df60d3d0d0~tplv-k3u1fbpfcp-watermark.awebp'
},
{
img: 'https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/40135df7df034eb5a76daa76f26fe046~tplv-k3u1fbpfcp-watermark.awebp'
},
{
img: 'https://img0.baidu.com/it/u=3377517910,1108839715&fm=26&fmt=auto'
}
]
}
},
methods: {
setViewer(panorama) {
if (this.viewer) try {
this.viewer.destroy()
} catch (e) {
console.log(e)
const viewer = document.querySelector('#viewer')
viewer.removeChild(viewer.childNodes[0])
}
this.viewer = new Viewer({
container: document.querySelector('#viewer'),
panorama,
size: {
width: '886px',
height: '554px'
},
plugins: [
[
MarkersPlugin,
{
markers: [
]
}
]
]
})
this.viewer.once('ready', () => {
console.log('ready')
// 自动旋转
this.viewer.startAutorotate()
})
this.markersPlugin = this.viewer.getPlugin(MarkersPlugin)
this.markersPlugin.on('select-marker', (e, marker) => {
// 点击选中标注
console.log('select-marker e:', e)
console.log('marker:', marker)
if (e.args[0].config.note) this.setViewer(this.itemArr[e.args[0].config.note].img)
})
this.viewer.on('click', (e, data) => {
// 添加标注
const num = 1 + Math.round(Math.random() * 2)
console.log('num:', num)
this.markersPlugin.addMarker({
id: `mark${Math.random() * 10}`,
tooltip: `213123
<p>点击标注跳去${num + 1}全景图</p></p>
<img style="width:100px;height:100px;" src="https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fp0.ssl.cdn.btime.com%2Ft0109595b67ee2b1409.jpg%3Fsize%3D640x400&refer=http%3A%2F%2Fp0.ssl.cdn.btime.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1638584229&t=abda6688f0689b74f3a20368e31f65c1" />
`,
html: `
<p class="remark">点击标注跳去${num + 1}全景图</p>
<p class="remark">这里是标记${
Math.floor(data.longitude * 100) / 100
} - ${Math.floor(data.latitude * 100) / 100}
</p>
<img src="https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fhbimg.b0.upaiyun.com%2F8d8c9a2823b7d858dd653159e3eb1c47b5032c32482e1-q2bcDa_fw658&refer=http%3A%2F%2Fhbimg.b0.upaiyun.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1638586036&t=475f829a3056851b1def0ec6de05a596" />
`,
longitude: data.longitude,
latitude: data.latitude,
anchor: 'center center',
note: num
})
let configArr = Object.keys(this.markersPlugin.markers).map(
(item) => this.markersPlugin.markers[item].config
)
localStorage.setItem('configArr', JSON.stringify(configArr))
})
}
},
mounted() {
this.setViewer(this.itemArr[0].img)
const configArr = JSON.parse(localStorage.getItem('configArr'))
this.viewer.once('ready', () => {
configArr.forEach((item) => {
this.markersPlugin.addMarker(item)
})
})
}
}
</script>
<style lang="scss" scoped>
.demo-container {
position: relative;
min-width: 1439px;
margin: 0 auto;
#viewer {
margin: 0 auto;
::v-deep .psv-container {
.psv-marker {
border: 1px solid white;
padding: 10px;
.remark {
padding: 10px 15px;
color: white;
}
img {
width: 20px;
height: 20px;
margin: 0 auto;
display: block;
}
}
.psv-tooltip {
.psv-tooltip-content {
img {
width: 100px;
height: 100px;
margin: 0 auto;
display: block;
}
}
}
}
}
.item-container {
text-align: center;
margin-top: 20px;
li {
cursor: pointer;
display: inline-block;
padding: 10px 20px;
&:hover {
background-color: blue;
color: white;
}
}
}
}
</style>
项目中效果图
全景图编辑标注
推荐阅读
photo-sphere-viewer中文文档
Vue源码学习目录
谢谢你阅读到了最后~
期待你关注、收藏、评论、点赞~
让我们一起 变得更强
更多推荐
所有评论(0)