photo-sphere-viewer 全景图Vr 720全景查看(vue篇)

news/2024/11/23 3:11:56/

一、安装以及引入方式

npm install @photo-sphere-viewer/core
/***插件安装**/
npm install @photo-sphere-viewer/markers-plugin
npm install @photo-sphere-viewer/gallery-plugin
npm install @photo-sphere-viewer/autorotate-plugin

二、PhotoSphereViewer.vue

<template><div id="viewer"></div>
</template><script>
import { Viewer } from "@photo-sphere-viewer/core";
import { MarkersPlugin } from "@photo-sphere-viewer/markers-plugin";
import { GalleryPlugin } from "@photo-sphere-viewer/gallery-plugin";
import { AutorotatePlugin } from "@photo-sphere-viewer/autorotate-plugin";
import "@photo-sphere-viewer/core/index.css";
import "@photo-sphere-viewer/markers-plugin/index.css";
import "@photo-sphere-viewer/gallery-plugin/index.css";
export default {props: {hasAnimate: {type: Boolean,default: true,},imgList: [],hasGallery: {type: Boolean,default: true,},},components: {},data() {return {viewer: "",panoramaUrl: "",markersPlugin: "",autorotatePlugin: "",galleryPlugin: "",currIndex: 0,animatedValues: {pitch: { start: -Math.PI / 2, end: 0.2 },yaw: { start: Math.PI, end: 0 },zoom: { start: 0, end: 50 },fisheye: { start: 2, end: 0 },},defaultUrl: require("../assets/3.jpg"),};},created() {},mounted() {this.panoramaUrl = this.imgList[0].panorama || this.defaultUrl;this.initViewer();this.handelListenerViewerClick();this.handleSelectMarker();this.handleHoverMarker();this.handleLeaveMarker();this.$nextTick(() => {this.handleGalleryChange();});},watch: {},methods: {initViewer() {const _this = this;this.viewer = new Viewer({container: "viewer",panorama: this.panoramaUrl || this.defaultUrl,caption: "test",loadingImg: require("../assets/loader.gif"),touchmoveTwoFingers: true,mousewheelCtrlKey: false,navbar: ["autorotate","zoom","markers","move","download","gallery",{title: "Change points",content: "🔄",onClick: _this.randomPoints,},"caption","fullscreen",],plugins: [[GalleryPlugin,{visibleOnLoad: true,hideOnClick: false,},],[AutorotatePlugin,{autostartDelay: null,/*   autorotatePitch: _this.animatedValues.pitch.end,autostartOnIdle: false, */autorotateSpeed: "1rpm",},],[MarkersPlugin,{markers: [],},],],});_this.markersPlugin = _this.viewer.getPlugin(MarkersPlugin);_this.autorotatePlugin = _this.viewer.getPlugin(AutorotatePlugin);_this.galleryPlugin = _this.viewer.getPlugin(GalleryPlugin);if (_this.hasGallery) {_this.galleryPlugin.setItems(_this.imgList); //设置图库}_this.viewer.addEventListener("ready", _this.handleViewerReady, {once: true,});},handleViewerReady() {this.markersPlugin.setMarkers(this.imgList[this.currIndex].markers); //设置标签this.showInitMarker();},showInitMarker() {const _this = this;this.viewer.animate({yaw: "-27deg",pitch: "-6deg",speed: 100,}).then(() => {_this.markersPlugin.showMarkerTooltip("new-marker1");_this.autorotatePlugin.start();});},//清除标记clearMarker() {this.markersPlugin.clearMarkers();},//更新标记updateMarker(id, imgUrl) {this.markersPlugin.updateMarker({id: id,image: imgUrl,});},updateIndex(index) {this.currIndex = index;this.panoramaUrl = this.imgList[index].panorama;},//选择标记事件handleSelectMarker() {const _this = this;this.markersPlugin.addEventListener("select-marker", ({ marker }) => {this.$emit("selectMarker", marker);});},//标记悬停事件handleHoverMarker() {this.markersPlugin.addEventListener("enter-marker", ({ marker }) => {/*  console.log("enter"); */});},handleLeaveMarker() {this.markersPlugin.addEventListener("leave-marker", ({ marker }) => {/* console.log("leave"); */});},//gallery图库列表切换handleGalleryChange() {const _this = this;let _sindex = "";document.addEventListener("click", function (e) {var element = document.elementFromPoint(e.clientX, e.clientY);let flag = false;if (element && element.dataset && element.dataset.psvGalleryItem) {const id = element.dataset.psvGalleryItem;_sindex = _this.imgList.findIndex((data) => {return data.id == id;});flag = true;} else {if (element&&element.className == "psv-gallery-item-thumb") {const eleId =element.parentElement.parentElement.dataset.psvGalleryItem;_sindex = _this.imgList.findIndex((data) => {return data.id == eleId;});flag = true;}}if (flag) {if (_this.currIndex == _sindex) {console.log("点击了未切换");} else {_this.currIndex = _sindex;_this.panoramaUrl = _this.imgList[_sindex].panorama;_this.handelChangeViewer("gallery");}}});},//图库列表当前选中active更新handelGalleryActive() {const galleryBox = document.getElementsByClassName("psv-gallery-container")[0];const galleryItemEle =document.getElementsByClassName("psv-gallery-item")[this.currIndex];galleryBox.childNodes.forEach((item) => {item.className = "psv-gallery-item";});galleryItemEle.classList.add("psv-gallery-item--active");},/**** viewer 切换场景* */handelChangeViewer(type) {const _this = this;if (_this.viewer) {_this.clearMarker();_this.handelGalleryActive();_this.viewer.setPanorama(_this.panoramaUrl).then(() => {_this.markersPlugin.setMarkers(_this.imgList[_this.currIndex].markers);});if (type != "gallery") {this.handelGalleryActive();}}},//viewer点击事件监听handelListenerViewerClick(addMarker) {const _this = this;const emptyMarker = {image: require("./../assets/local.png"),width: 32,height: 32,};addMarker = addMarker ? addMarker : emptyMarker;this.viewer.addEventListener("click", ({ data }) => {if (!data.rightclick) {_this.$emit("viewerClick", data);_this.markersPlugin.addMarker({id: "#" + Math.random(),position: { yaw: data.yaw, pitch: data.pitch },image: addMarker.image || require("./../assets/local.png"),size: {width: addMarker.width || 32,height: addMarker.height || 32,},anchor: "bottom center",tooltip: addMarker.tooltip || "新增标记",data: {generated: true,},});}});},randomPoints() {/*  this.markersPlugin.showMarkerTooltip("new-marker3"); */this.markersPlugin.showAllTooltips();},},
};
</script>
<style lang="scss" scoped>
#viewer {width: 100%;height: 100%;
}
</style>

图库列表切换场景及图标点击切换实现场景

注:图库插件本身对于图库列表切换,场景的标记点会是初始时设置的标记点,不会更新新的标记点,需要自己写监听调用更新标记的方法(handleGalleryChange)。同时对于标记切换场景用了viewer.setPanorama,图库列表当前选中的active没有同步,需要调用自己写的方法handelGalleryActive,同步当前的图片active样式

图库列表切换

handleGalleryChange() {const _this = this;let _sindex = "";document.addEventListener("click", function (e) {var element = document.elementFromPoint(e.clientX, e.clientY);let flag = false;if (element && element.dataset && element.dataset.psvGalleryItem) {const id = element.dataset.psvGalleryItem;_sindex = _this.imgList.findIndex((data) => {return data.id == id;});flag = true;} else {if (element&&element.className == "psv-gallery-item-thumb") {const eleId =element.parentElement.parentElement.dataset.psvGalleryItem;_sindex = _this.imgList.findIndex((data) => {return data.id == eleId;});flag = true;}}if (flag) {if (_this.currIndex == _sindex) {console.log("点击了未切换");} else {_this.currIndex = _sindex;_this.panoramaUrl = _this.imgList[_sindex].panorama;_this.handelChangeViewer("gallery");}}});},//图库列表当前选中active更新handelGalleryActive() {const galleryBox = document.getElementsByClassName("psv-gallery-container")[0];const galleryItemEle =document.getElementsByClassName("psv-gallery-item")[this.currIndex];galleryBox.childNodes.forEach((item) => {item.className = "psv-gallery-item";});galleryItemEle.classList.add("psv-gallery-item--active");},/**** viewer 切换场景* */handelChangeViewer(type) {const _this = this;if (_this.viewer) {_this.clearMarker();_this.handelGalleryActive();_this.viewer.setPanorama(_this.panoramaUrl).then(() => {_this.markersPlugin.setMarkers(_this.imgList[_this.currIndex].markers);});if (type != "gallery") {this.handelGalleryActive();}}},

选择标签切换: 

this.markersPlugin.addEventListener("select-marker", ({ marker }) => {this.handelChangeViewer();});

三、页面调用 

<template><div class=""><photoSphereViewerstyle="width: 80vw; height: 90vh"ref="viewer":imgList="photoList"@selectMarker="selectMarker"/></div>
</template><script>
import photoSphereViewer from "@/components/PhotoSphereViewer.vue";
import { markers, photos } from "@/components/data.js";
export default {props: [],components: { photoSphereViewer },data() {return {photoList: photos,};},created() {},mounted() {},methods: {selectMarker(marker) {console.log("here page");console.log(marker);const myViewer = this.$refs.viewer;if (marker.id == "new-marker1") {myViewer.updateIndex(1);}if (marker.id == "new-marker2") {myViewer.updateIndex(2);}if (marker.id == "new-marker3") {myViewer.updateMarker(marker.id, require("./../../assets/bao.png"));} else {myViewer.handelChangeViewer();}},},
};
</script>
<style lang="scss" scoped>
</style>

四、模拟数据

/**标记点**/
export const markers = [{id: 'new-marker1',position: {yaw: '-27deg',pitch: '-6deg'},image: require('./../assets/arrow.gif'),size: {width: 50,height: 50},tooltip: {content: "go ahead",className: 'custom-tooltip',position: 'top',trigger: 'chan',},},{id: 'new-marker2',position: {yaw: '-170deg',pitch: '20deg'},image:require('./../assets/arrow.gif'),size: {width: 50,height: 50},},{id: 'new-marker3',tooltip: {content: "恭喜你,获得意外宝藏!",class: 'custom-tooltip',position: 'top',trigger: 'click'},position: {yaw: '4deg',pitch: '-52deg'},image: require('./../assets/local.png'),size: {width: 38,height: 38},anchor: 'Holly',},{// polyline markerid: 'polyline',polylinePixels: [[2478, 1635], [2184, 1747], [1674, 1953], [1166, 1852],[709, 1669], [301, 1519], [94, 1399], [34, 1356],],svgStyle: {stroke: 'rgba(140, 190, 10, 0.8)',strokeLinecap: 'round',strokeLinejoin: 'round',strokeWidth: '10px',},tooltip: 'A dynamic polyline marker',},
];
/**全景图片列表**/
export const photos = [{id: 'sphere',panorama:require('./../assets/3.jpg'),thumbnail: require('./../assets/3.jpg'),options: {caption: '图一',},markers:markers},{id: 'sphere-test',panorama: require('./../assets/2.jpg'),thumbnail: require('./../assets/2.jpg'),name: 'Test sphere',options: {caption: '图二',},markers:[{id: 'new-marker21',position: {yaw: '-27deg',pitch: '-6deg'},image: require('./../assets/arrow.gif'),size: {width: 50,height: 50},},]},{id: 'key-biscayne',panorama: require('./../assets/1.jpg'),thumbnail: require('./../assets/1.jpg'),name: 'Key Biscayne',options: {caption: '图三',},markers:[ ]},
]

五、补充入场动画(引入utils)

import { Viewer, utils } from "@photo-sphere-viewer/core";
  //定义动画参数animatedValues: {pitch: { start: -Math.PI / 2, end: 0.2 },yaw: { start: Math.PI, end: 0 },zoom: { start: 0, end: 50 },fisheye: { start: 2, end: 0 },},//入场动画enteraAimation() {const _this = this;/*  _this.autorotatePlugin.stop(); */new utils.Animation({properties: _this.animatedValues,duration: 2500,easing: "inOutQuad",onTick: (properties) => {_this.viewer.setOption("fisheye", properties.fisheye);_this.viewer.rotate({ yaw: properties.yaw, pitch: properties.pitch });_this.viewer.zoom(properties.zoom);},}).then(() => {if (this.hasGallery) {this.galleryPlugin.setItems(this.imgList); //设置图库}/*  _this.autorotatePlugin.start(); */});},

六、事件整理

1.viewer

1)全屏

viewer.enterFullscreen();//全屏viewer.exitFullscreen();//退出全屏viewer.toggleFullscreen();//全屏切换viewer.isFullscreenEnabled();//获取当前全屏状态

2)pannel

//监听 panel显示
this.viewer.addEventListener("show-panel", ({ panelId }) => {if (panelId === PANEL_ID) {viewer.navbar.getButton(BUTTON_ID).toggleActive(true);} 
});
//监听 panel隐藏
this.viewer.addEventListener("hide-panel", ({ panelId }) => {if (panelId === PANEL_ID) {viewer.navbar.getButton(BUTTON_ID).toggleActive(false);} 
});//panel隐藏this.viewer.panel.hide();//panel显示
this.viewer.panel.show({id: id,width: "100%",content: value,
})

 3)获取view相关信息

const position = viewer.getPosition();const zoom =viewer.getZoomLevel();const size = viewer.getSize();

4)对viewer的set

//rorate
viewer.rotate({yaw:0,pitch:0});//切换场景图
viewer.setPanorama('image.jpg').then(() => /* update complete */);//setOptions
viewer.setOptions({defaultPitch: animatedValues.pitch.end,defaultYaw: animatedValues.yaw.end,defaultZoomLvl: animatedValues.zoom.end,});

5)其他监听事件

//position更新
viewer.addEventListener('position-updated', ({ position }) => ());//view点击
viewer.addEventListener('click', ({ data }) => {console.log(`${data.rightclick ? 'right ' : ''}clicked at yaw: ${data.yaw} pitch: ${data.pitch}`);
});//view Ready
viewer.addEventListener('ready', () => {console.log(`viewer is ready`);
}, { once: true });//zoom-updated
viewer.addEventListener('zoom-updated', ({ zoomLevel }) => {console.log(`new zoom level is ${zoomLevel}`);
});

2.MarkersPlugin

//tooltip全部显示
markersPlugin.showAllTooltips();//清除标记
markersPlugin.clearMarkers();//更新标记
markersPlugin.updateMarker({id: id,image: imgUrl,
});
//设置标记
markersPlugin.setMarkers(markers)//选中标记
markersPlugin.addEventListener("select-marker", ({ marker }) => {  });//标记悬停markersPlugin.addEventListener("enter-marker", ({ marker }) => {/*  console.log("enter"); */});
this.markersPlugin.addEventListener("leave-marker", ({ marker }) => {/* console.log("leave"); */});

3.AutorotatePlugin

//自动旋转停止
autorotatePlugin.stop();//开始自动自动旋转
autorotatePlugin.start();

4.GalleryPlugin

//图库列表显示
galleryPlugin.show();
//图库列表隐藏
galleryPlugin.hide();
//图库列表切换
galleryPlugin.toggle();


http://www.ppmy.cn/news/280171.html

相关文章

Unity 制作360全景视频 全景图片流程

Recorder的使用 在Unity制作360图片或者视频需要用到UnityPackage:Recorder 如果没有就在Package Manager寻找 1、在菜单栏找到Window/General/Recorder/RecorderWindow 参数说明: Animation Clip&#xff1a;录制动画剪辑 Movie&#xff1a;录制视频 Image Sequence&a…

vue实现vr看360°全景效果

1&#xff1a;首先创建一个vue的基础项目 vue create demo 2&#xff1a;启动并打开项目 3&#xff1a;在生成的public文件夹下找到Index.html&#xff0c;然后在script标签中引入three.js <script src"https://cdn.jsdelivr.net/npm/three0.93.0/build/three.min.js&…

4K高清视频素材,拿去不谢。

推荐几个高清视频素材网站&#xff0c;重点是可以免费下载&#xff0c;还可以商用&#xff0c;记得收藏哦&#xff01; 1、菜鸟图库 https://www.sucai999.com/video.html?vNTYwNDUx 菜鸟图库是一个素材量非常大得网站&#xff0c;站内不仅有非常多高清视频素材之外&#x…

Vue使用photo-sphere-viewer360°×180°全景插件模拟VR看房、房间切换

近两年随着VR的火热&#xff0c;市面上也出现了很多购房和二手房软件小程序出现了VR看房功能&#xff0c;实现足不出户就能亲身体验&#xff0c;那么类似这样的功能是怎么实现的呢&#xff1f; 今天阿七就和大家一起来学习一下360180全景插件photo-sphere-viewer和他的插件&am…

二、H5全景图-朋友圈全景图-720°全景-VR ---- 项目简单分析

原文地址&#xff1a; http://blog.csdn.net/qq_24889075/article/details/51974204 http://www.jianshu.com/p/a1b8707e3e08 本文纯属个人观点&#xff0c;如有错误请指点 官方网站 这里我们主要看一下生成的项目中都有什么。源码中都有什么&#xff0c;如何去自定义 我们…

前端使用UtoVR Player全景视频播放器实现360°C全景VR视频

准备&#xff1a; 官网&#xff1a;http://www.utovr.com Web包git下载地址&#xff1a;https://github.com/u10k/utovr.git UtoVR Player介绍&#xff1a; UtoVR Player是一款全景视频播放器。它支持360度空间全景视频的播放。观看者通过与播放器的交互&#xff0c;可以体验…

UE4中采集360°全景图片和视频

UE4中导出全景图片和视频 1.插件测试—采集单帧双眼图像 打开Epic Games Launcher&#xff0c;启动引擎&#xff08;我使用的版本为4.14.0&#xff09;。在弹出的对话框中点击New Project标签栏&#xff0c;再选择C标签页&#xff0c;选择Vehicle Advanced模板&#xff0c;并将…

准备跳槽的兄弟可以看看...

八股文为什么这么火爆&#xff1f; 因为只要大家技术和能力过关&#xff0c;八股文能帮助大家在面试时有很好的表现和稳定的发挥&#xff0c;让面试官预估到你能带来的价值&#xff0c;从而实现薪资高涨幅。 总结了一些小伙伴的面试经验&#xff0c;和我自己多年的资料库存&a…