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

一、安装以及引入方式

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="">
    <photoSphereViewer
    style="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 marker
        id: '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();

评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值