一、安装以及引入方式
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();