开源全景插件 Photo Sphere Viewer

1,650 阅读3分钟

概述

日常中,我们比较常见的是街区全景,百度通过街景车采集街景数据,最后形成全景应用,百度的全景还拥有一定的交互功能,可以随着街道移动街景,作为个人开发者,有一些开源库能够满足我们对全景的应用与探索。Aframe是一个功能强大的框架,我们也可以通过它实现全景功能,Photo Sphere Viewer,一个使用Three实现的全景库,接下来,我将简析该库的使用。

入门

  1. 安装
// 安装
npm install photo-sphere-viewer
// 安装依赖
npm install three.js uevent
  1. html 不要忘记设置div的宽高
<div id="viewer"></div>
  1. 初始化
import { Viewer } from 'photo-sphere-viewer';

const viewer = new Viewer({
  container: document.querySelector('#viewer'),
  panorama: 'test.jpg' // 图片地址
});

测试图片地址

深入使用

多张图片的全景数据

现在的全景数据有很多种,我们入门使用的便是全景数据为一整张的情况,也会有多长图片的情况,甚至是以瓦片形式的全景数据。

panorama: 'test.jpg' // 图片地址
//如果是多张可以组织一下,同样传入该属性中
// 数组写法需要注意顺序
panorama: [
  'left.jpg', 'front.jpg',
  'right.jpg', 'back.jpg',
  'top.jpg', 'bottom.jpg',
]
// 对象写法也是可以的,两者都能支持多张图片的传入
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',
}

测试图片1组 测试图片2组

增加标记

当我们体验全景功能时,自然会想要一些交互效果,该开源库便支持此效果,它允许你在全景上用任意图标标记点位,或绘画一片区域,又或者是增加一段文字,并且可以进行点击交互。 这里贴上长代码进行解释,点击查看在线示例

var viewer = new PhotoSphereViewer.Viewer({
  panorama: 'https://photo-sphere-viewer-data.netlify.app/assets/sphere.jpg',
  container: 'photosphere',
  
  defaultLat: 0.3,
  touchmoveTwoFingers: true,
  mousewheelCtrlKey: true, // 是否启用ctrl+滚轮缩放
  // 插件列表
  plugins: [
    //   标记插件
    [PhotoSphereViewer.MarkersPlugin, {
    //   标记列表
      markers: [{
          // 该标记会弹出弹窗
          id: 'image',
          longitude: 0.32,
          latitude: 0.11,
          image: 'https://photo-sphere-viewer.js.org/assets/pin-blue.png',
          width: 32,
          height: 32,
          anchor: 'bottom center',
          tooltip: 'A image marker. <b>Click me!</b>', //提示框
          content: document.getElementById('lorem-content').innerHTML // 弹窗内容
        },
        {
          // 自定义样式的标记
          id: 'text',
          longitude: 0,
          latitude: 0,
          html: 'HTML <b>marker</b> &hearts;', // 显示内容
          anchor: 'bottom right',
          scale: [0.5, 1.5],
          style: {
            maxWidth: '100px',
            color: 'white',
            fontSize: '20px',
            fontFamily: 'Helvetica, sans-serif',
            textAlign: 'center'
          },
          tooltip: {
            content: 'An HTML marker',
            position: 'right'
          }
        },
        {
          // 面标记
          id: 'polygon',
          polylineRad: [
            [6.2208, 0.0906],
            [0.0443, 0.1028],
            [0.2322, 0.0849],
            [0.4531, 0.0387],
            [0.5022, -0.0056],
            [0.4587, -0.0396],
            [0.2520, -0.0453],
            [0.0434, -0.0575],
            [6.1302, -0.0623],
            [6.0094, -0.0169],
            [6.0471, 0.0320],
            [6.2208, 0.0906],
          ],
          svgStyle: {
            fill: 'rgba(200, 0, 0, 0.2)',
            stroke: 'rgba(200, 0, 50, 0.8)',
            strokeWidth: '2px'
          },
          tooltip: {
            content: 'A dynamic polygon marker',
            position: 'right bottom'
          }
        },
        {
          // 线标记
          id: 'polyline',
          polylinePx: [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'
        },
        {
          // 园标记
          id: 'circle',
          circle: 20,
          x: 2500,
          y: 1000,
          tooltip: 'A circle marker'
        }
      ]
    }]
  ]
});

var markersPlugin = viewer.getPlugin(PhotoSphereViewer.MarkersPlugin);

/**
 * 点击创建新的标记
 */
viewer.on('click', function(e, data) {
  if (!data.rightclick) {
    markersPlugin.addMarker({
      id: '#' + Math.random(),
      longitude: data.longitude,
      latitude: data.latitude,
      image: 'https://photo-sphere-viewer.js.org/assets/pin-red.png',
      width: 32,
      height: 32,
      anchor: 'bottom center',
      tooltip: 'Generated pin',
      data: {
        generated: true
      }
    });
  }
});

/**
 * 双击删除标记
 * 右击改变图标图片
 */
markersPlugin.on('select-marker', function(e, marker, data) {
  if (marker.data && marker.data.generated) {
    if (data.dblclick) {
      markersPlugin.removeMarker(marker);
    } else if (data.rightclick) {
      markersPlugin.updateMarker({
        id: marker.id,
        image: 'https://photo-sphere-viewer.js.org/assets/pin-blue.png',
      });
    }
  }
});

关于坐标系统,这里有两套坐标系统,一套为纹理坐标,另一套为弧度坐标,纹理坐标不能在多图全景中使用。

总结

从依赖关系上看,该库是基于three与uevent开发完成,three实现全景基础功能,uevent实现相关监听事件,如果想要继续研究的话,可以自己跑一下three官方的这几个示例:示例1,示例2,示例3,搞清这几个,自己便能实现一个全景功能。 正如我开头讲过的,还有另一个能够实现全景的库Aframe,这个库相对大一些,因为它不仅仅能实现全景功能,它更能实现AR功能等功能,我会在另一篇文章中介绍它。

欢迎来到我的个人博客