官方网站:https://photo-sphere-viewer.js.org/
线上demo:点击查看
需要引入的文件
<link rel="stylesheet" href="./css/photo-sphere-viewer.min.css">
<!-- 3D -->
<script src="./js/three.min.js"></script>
<!-- js语言修补匠,可向后兼容,适用于低版本浏览器 -->
<script src="./js/polyfill.js"></script>
<!-- 事件发射器库,它为javascript对象提供观察者模式 -->
<script src="./js/uevent.min.js"></script>
<!-- 模板引擎 -->
<script src="./js/doT.min.js"></script>
<!-- 阻止睡眠 -->
<script src="./js/NoSleep.js"></script>
<!-- 处理手机陀螺仪方向 -->
<script src="./js/DeviceOrientationControls.js"></script>
<!-- 双屏渲染 -->
<script src="./js/StereoEffect.js"></script>
<!-- 全景图插件 -->
<script src="./js/photo-sphere-viewer.js"></script>
创建一个div
<!-- 全景图 -->
<div id="photo-sphere">
<div id="viewer"></div>
</div>
调用PhotoSphereViewer
方法
<script>
var viewer = new PhotoSphereViewer({
container: 'viewer',
panorama: 'path/to/panorama.jpg',
size:{
width:'100%',
height:'100%'
}
});
</script>
写下面这些代码就可以加载全景图
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
body {
margin: 0;
padding: 0;
}
#photo-sphere {
width: 80%;
height: 500px;
margin: 100px auto;
box-shadow: 5px 5px 20px rgba(0, 0, 0, 0.4);
}
</style>
<link rel="stylesheet" href="css/photo-sphere-viewer.css">
<script src="libs/three.js"></script>
<script src="libs/D.js"></script>
<script src="libs/uevent.js"></script>
<script src="libs/doT.js"></script>
<script src="libs/DeviceOrientationControls.js"></script><!-- 使用陀螺仪加入此js库文件 -->
<script src="libs/photo-sphere-viewer.js"></script>
</head>
<body>
<!-- 全景图 -->
<div id="photo-sphere">
<div id="viewer"></div>
</div>
<script>
var viewer = new PhotoSphereViewer({
container: 'viewer',
panorama: 'img/3.jpg',
size:{
width:'100%',
height:'100%'
}
});
</script>
</body>
</html>
完整代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>PhotoSphereViewer - equirectangular demo</title>
<link rel="stylesheet" href="./css/photo-sphere-viewer.min.css">
<style>
html, body {
width: 100%;
height: 100%;
overflow: hidden;
margin: 0;
padding: 0;
}
#photosphere {
width: 100%;
height: 100%;
}
.psv-button.custom-button {
font-size: 22px;
line-height: 20px;
}
.demo-label {
color: white;
font-size: 20px;
font-family: Helvetica, sans-serif;
text-align: center;
padding: 5px;
border: 1px solid white;
background: rgba(0,0,0,0.4);
}
</style>
</head>
<body>
<div id="photosphere"></div>
<!-- 3D -->
<script src="./js/three.min.js"></script>
<!-- js语言修补匠,可向后兼容,适用于低版本浏览器 -->
<script src="./js/polyfill.js"></script>
<!-- 事件发射器库,它为javascript对象提供观察者模式 -->
<script src="./js/uevent.min.js"></script>
<!-- 模板引擎 -->
<script src="./js/doT.min.js"></script>
<!-- 阻止睡眠 -->
<script src="./js/NoSleep.js"></script>
<!-- 处理手机陀螺仪方向 -->
<script src="./js/DeviceOrientationControls.js"></script>
<!-- 双屏渲染 -->
<script src="./js/StereoEffect.js"></script>
<!-- 全景图插件 -->
<script src="./js/photo-sphere-viewer.js"></script>
<!-- 用于标记说明的文字 -->
<script type="text/template" id="pin-content">
<h1>来自HTML的礼物</h1>
<p><strong>说明文字1</strong> senectus et netus et malesuada fames ac turpis egestas.
Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas
semper. <em>Aenean ultricies mi vitae est.</em> Mauris placerat eleifend leo. Quisque sit amet est et sapien
ullamcorper pharetra. Vestibulum erat wisi, condimentum sed, <code>commodo vitae</code>, ornare sit amet, wisi.
Aenean fermentum, elit eget tincidunt condimentum, eros ipsum rutrum orci, sagittis tempus lacus enim ac dui. <a
href="#">Donec non enim</a> in turpis pulvinar facilisis. Ut felis.</p>
<h2>Header Level 2</h2>
<ol>
<li>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</li>
<li>Aliquam tincidunt mauris eu risus.</li>
</ol>
<blockquote><p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus magna. Cras in mi at felis aliquet
congue. Ut a est eget ligula molestie gravida. Curabitur massa. Donec eleifend, libero at sagittis mollis, tellus
est malesuada tellus, at luctus turpis elit sit amet quam. Vivamus pretium ornare est.</p></blockquote>
<h3>Header Level 3</h3>
<ul>
<li>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</li>
<li>Aliquam tincidunt mauris eu risus.</li>
</ul>
<img src="assets/pin2.png" style="width:100%"/>
<pre><code>
#header h1 a {
display: block;
width: 300px;
height: 80px;
}
</code></pre>
</script>
<!-- 用于多边形标记的图案 -->
<svg id="patterns">
<defs>
<pattern id="dots" x="10" y="10" width="30" height="30" patternUnits="userSpaceOnUse">
<circle cx="10" cy="10" r="10" style="stroke: none; fill: rgba(255,0,0,0.4)"/>
</pattern>
<pattern id="points" x="10" y="10" width="15" height="15" patternUnits="userSpaceOnUse">
<circle cx="10" cy="10" r="0.8" style="stroke: none; fill: red"/>
</pattern>
</defs>
</svg>
<script>
var panos = [
{
url: 'Bryce-Canyon-National-Park-Mark-Doliner.jpg',
desc: 'Bryce Canyon National Park <b>© Mark Doliner</b>',
target: {
longitude: 3.848,
latitude: -0.244,
zoom: 50
}
}, {
url: 'Bryce-Canyon-By-Jess-Beauchemin.jpg',
desc: 'Bryce Canyon National Park <b>© Jess Beauchemin</b>',
target: {
longitude: 3.715,
latitude: 0.574,
zoom: 50
}
}
];
var PSV = new PhotoSphereViewer({
container: 'photosphere', //必选,放置全景图的容器
panorama: panos[0].url, //必选,全景图的路径
caption: panos[0].desc, //描述
loading_img: 'assets/photosphere-logo.gif', //加载文件时的图片路径
longitude_range: [-7 * Math.PI / 8, 7 * Math.PI / 8], //经度范围
latitude_range: [-3 * Math.PI / 4, 3 * Math.PI / 4], //维度范围
anim_speed: '-2rpm', //旋转速度
default_fov: 50, //初始视野,最小视野和最大视野之间
fisheye: true, //使用true启用鱼眼效果或指定效果强度(true=1.0)此模式可能会对标记渲染产生副作用。
move_speed: 1.1, //移动速度
time_anim: false, //全景图自动开始旋转之前的空闲时间(毫秒)。禁用为False。
// touchmove_two_fingers: true, //需要两个手指来旋转全景。这允许在包含查看器的页面中进行标准的触摸滚动导航。如果启用,当仅检测到一次触摸时,将显示要求用户使用两个手指的覆盖。
// mousemove_hover: true, //旋转全景只需移动光标,以查看是否需要点击+移动。
navbar: [ //导航栏是一个数组,它可以包含以下核心按钮:自动旋转、缩放、下载、标记、陀螺仪、立体声、全屏,以及用于创建自定义按钮的标题和对象
'autorotate', 'zoom', 'download', 'markers',
{
title: 'Change image', //按钮的名字
className: 'custom-button', //添加到button元素的CSS类
content: '🔄', //显示的文本
onClick: (function() { //点击时触发的事件
var i = 0;
var loading = false;
return function() {
if (loading) {
return;
}
i = 1 - i;
loading = true;
PSV.clearMarkers(); //清除所有标记
PSV.setPanorama(panos[i].url, panos[i].target, true) //加载新的全景文件
.then(function() {
PSV.setCaption(panos[i].desc);
loading = false;
});
}
}())
},
{
title : 'Random position',
className: 'custom-button',
content: '🔀',
onClick: function() {//点击时触发的事件
PSV.animate({ //动画
longitude: (Math.random() - 0.5) * 3 / 2 * Math.PI,
latitude: (Math.random() - 0.5) * 3 / 4 * Math.PI,
zoom: Math.random() * 60 + 20
}, 1500);
}
},
'caption', 'gyroscope', 'stereo', 'fullscreen'
],
//标记,https://photo-sphere-viewer.js.org/markers.html
markers: (function() {
var a = [];
for (var i = 0; i < Math.PI * 2; i += Math.PI / 4) {
for (var j = -Math.PI / 2 + Math.PI / 4; j < Math.PI / 2; j += Math.PI / 4) {
a.push({
id: '#' + a.length, //唯一标识
tooltip: '#' + a.length,//定义工具提示的标记或对象的工具提示内容。
latitude: j, //维度
longitude: i, //经度
image: 'assets/pin1.png', //图片路径
width: 32, //宽
height: 32, //高
anchor: 'bottom center', //定义标记朝其位置放置的位置。任何CSS位置对于多边形/折线都是有效的,例如bottom center或被20% 80%
data: { //您要附加到标记的任何自定义数据
deletable: true
}
});
}
}
a.push({
id: 'lorem',
tooltip: {
content: 'Lorem ipsum dolor ist amet et consecturo.',
position: 'bottom right'
},
content: document.getElementById('pin-content').innerHTML,
latitude: 0,
longitude: 0.20,
image: 'assets/pin2.png',
width: 32,
height: 32,
anchor: 'bottom center'
});
a.push({
id: 'polygon-sky',
svgStyle: {
fill: 'rgba(0, 190, 255, 0.1)'
},
polygon_rad: (function() {
var points = [];
for (var i = 0; i < Math.PI * 2; i += Math.PI / 8) {
points.push(i);
points.push(Math.PI / 8);
}
return points;
}())
});
a.push({
id: 'polygon',
content: 'This mountain is so great it has dots on it!',
polygon_px: [3184, 794, 3268, 841, 3367, 1194, 3327, 1307, 3065, 1221, 3097, 847],
svgStyle: {
fill: 'url(#points)', //'rgba(255,0,0,0.3)',
stroke: 'rgba(255, 0, 50, 0.8)',
strokeWidth: '2px'
},
tooltip: {
content: 'This is a mountain',
position: 'right bottom'
}
});
a.push({
id: 'polyline',
polyline_rad: [5.924, 0.064, 5.859, -0.061, 5.710, -0.132, 5.410, -0.287, 4.329, -0.490, 3.838, -0.370, 3.725, -0.241],
svgStyle: {
stroke: 'rgba(80, 100, 50, 0.8)',
strokeLinecap: 'round',
strokeLinejoin: 'round',
strokeWidth: '10px'
},
tooltip: 'This is a track'
});
a.push({
id: 'html-img-demo',
html: 'HTML & Image',
scale: [0.5, 1.5],
className: 'demo-label',
longitude: 0.5,
latitude: -0.48
});
a.push({
id: 'gif',
image: 'assets/photosphere-logo.gif',
width: 100,
height: 100,
longitude: 0.60,
latitude: -0.35
});
a.push({
id: 'text',
html: 'This <b>is</b> text <img src="assets/pin3.png" style="height: 24px; vertical-align: top;"/>',
anchor: 'bottom right',
style: {
color: 'white',
fontSize: '20px',
fontFamily: 'Helvetica, sans-serif',
textAlign: 'center'
},
longitude: 0.45,
latitude: -0.4
});
a.push({
id: 'svg-demo',
html: 'SVG marker demo',
scale: [0.5, 1.5],
className: 'demo-label',
longitude: -0.5,
latitude: -0.48
});
a.push({
id: 'circle',
tooltip: 'A circle of radius 30',
circle: 30,
svgStyle: {
fill: 'rgba(255,255,0,0.3)',
stroke: 'yellow',
strokeWidth: '2px'
},
longitude: -0.5,
latitude: -0.28,
anchor: 'center right'
});
a.push({
id: 'ellipse',
tooltip: 'An ellipse of radius 60/30',
ellipse: [60, 30],
svgStyle: {
fill: 'rgba(255,255,0,0.3)',
stroke: 'yellow',
strokeWidth: '2px'
},
longitude: -0.5,
latitude: -0.28,
anchor: 'center left'
});
a.push({
id: 'rect',
tooltip: 'A square a side 60',
rect: [60, 60],
svgStyle: {
fill: 'rgba(255,255,0,0.3)',
stroke: 'yellow',
strokeWidth: '2px'
},
longitude: -0.5,
latitude: -0.38,
anchor: 'center right'
});
a.push({
id: 'path',
tooltip: 'A custom path',
path: 'M 0 0 L 60 60 L 60 0 L 0 60 L 0 0',
svgStyle: {
fill: 'rgba(255,255,0,0.3)',
stroke: 'yellow',
strokeWidth: '2px'
},
longitude: -0.5,
latitude: -0.38,
anchor: 'center left'
});
a.push({
id: 'scale-demo',
html: 'Marker scale demo',
scale: [0.5, 1.5],
className: 'demo-label',
longitude: 0,
latitude: -0.48
});
a.push({
id: 'scale-0',
tooltip: 'No scale',
scale: false,
circle: 20,
svgStyle: {
fill: 'rgba(0, 0, 0, 0.5)'
},
longitude: -0.1,
latitude: -0.4
});
a.push({
id: 'scale-1',
tooltip: '<code>zoom x2</code>',
scale: 2,
circle: 20,
svgStyle: {
fill: 'rgba(0, 0, 0, 0.5)'
},
longitude: 0,
latitude: -0.4
});
a.push({
id: 'scale-2',
tooltip: '<code>zoom x0.5 ; zoom x1.5</code>',
scale: [0.5, 1.5],
circle: 20,
svgStyle: {
fill: 'rgba(0, 0, 0, 0.5)'
},
longitude: 0.1,
latitude: -0.4
});
return a;
}())
});
//全局事件
PSV.on('click', function(e) { //点击,则添加一个标记
PSV.addMarker({
id: '#' + Math.random(), //标记的唯一标识
tooltip: 'Generated marker',
longitude: e.longitude,
latitude: e.latitude,
image: 'assets/pin1.png',
width: 32,
height: 32,
anchor: 'bottom center',
data: {
deletable: true
}
});
});
PSV.on('select-marker', function(marker, dblclick) { //选择某个标记
if (marker.data && marker.data.deletable) {
if (dblclick) {
PSV.removeMarker(marker);
}
else {
PSV.updateMarker({
id: marker.id,
image: 'assets/pin2.png'
});
}
}
});
PSV.on('over-marker', function(marker) { //划过
console.log('over', marker.id);
});
PSV.on('leave-marker', function(marker) { //离开
console.log('leave', marker.id);
});
PSV.on('select-marker-list', function(marker) {
console.log('select-list', marker.id);
});
PSV.on('goto-marker-done', function(marker) {
console.log('goto-done', marker.id);
});
</script>
<script>
document.write('<script src="//' + location.host.split(':')[0] + ':35729/livereload.js" async defer><' + '/script>');
</script>
</body>
</html>
一些常用配置参数介绍
panorama:(必选)全景图的路径。
container:(必选)放置全景图的容器。
autoload:(默认为true)true为自动加载全景图,false为迟点加载全景图(通.过load方法)。
usexmpdata:(默认值为true)photo sphere viewer是否必须读入xmp数据,false为不必须。
cors_anonymous:(默认值为true)true为不能通过cookies获得用户
pano_size:(默认值为null)全景图的大小,是否裁切。
default_position:(默认值为0)定义默认位置,用户看见的第一个点,例如:{long: math.pi, lat: math.pi/2}。
min_fov:(默认值为30)观察的最小区域,单位degrees,在1-179之间。
max_fov:(默认值为90)观察的最大区域,单位degrees,在1-179之间。
allow_user_interactions:(默认值为true)设置为false,则禁止用户和全景图交互(导航条不可用)。
allow_scroll_to_zoom:(默认值为true)若设置为false,则用户不能通过鼠标滚动进行缩放图片。
tilt_up_max:(默认值为math.pi/2)向上倾斜的最大角度,单位radians。
tilt_down_max:(默认值为math.pi/2)向下倾斜的最大角度,单位radians。
min_longitude:(默认值为0)能够展示的最小经度。
max_longitude:(默认值为2PI)能够展示的最大维度。
zoome_level:(默认值为0)默认的缩放级别,值在0-100之间。
long_offset:(默认值为PI/360)mouse/touch移动时每像素经过的经度值。
lat_offset:(默认值为pi/180)mouse/touch移动时每像素经过的纬度值。
time_anim(默认值为2000)全景图在time_anim毫秒后会自动进行动画。(设置为false禁用它)
reverse_anim:(默认值为true)当水平方向到达最大/最小的经度时,动画方向是否反转(仅仅是不能看到完整的圆)。
anim_speed:(默认值为2rpm)动画每秒/分钟多少的速度。
vertical_anim_speed:(默认值为2rpm)垂直方向的动画每秒/分钟多少的速度。
vertical_anim_target:(默认值为0)当自动旋转时的维度,默认为赤道。
navbar:(默认为false)显示导航条。
navbar_style:(默认值为false)导航条的样式。有效的属性:
backgroundColor:导航条背景色(默认值rgba(61, 61, 61, 0.5));
buttonsColor:按钮前景色(默认值 rgba(255, 255, 255, 0.7));
buttonBackgroundColor:按钮激活时的背景色(默认值 rgba(255, 255, 255, 0.1));
buttonsHeight:按钮高度,单位px(默认值 20);
autorotateThickness:自动旋转图片的层(默认值 1);
zoomRangeWidth:缩放游标的宽度,单位px(默认值 50);
zoomRangeThickness:缩放游标的层(默认值 1);
zoomRangeDisk:缩放游标的放大率,单位px(默认值 7);
fullscreenRatio:全屏图标的比例(默认值 4/3);
fullscreenThickneee:全屏图片的层,单位px(默认值 2)
loading_msg:(默认值为Loading...)加载信息。
loading_img:(默认值 为null)loading图片的路径。
loading_html:(默认值 为null)html加载器(添加到容器中的元素或字符串)。
size:(默认值为null)全景图容器的最终尺寸,例如{width: 500, height: 300}。
onready:(默认值为null)全景图准备好并且第一张图片展示出来后的回调函数。
方法介绍
addAction():添加事件(插件没有提供执行事件的方法,似乎是提供给插件内部使用的)。
fitToContainer():调整全景图容器大小为指定大小。
getPosition():获取坐标经纬度。
getPositionInDegrees():获取经纬度度数。
getZoomLevel():获取缩放级别。
load():加载全景图()。
moveTo(longitude, latitude):根据经纬度移动到某一点。
rotate(dlong, dlat):根据经纬度度数移动到某一点。
toggleAutorotate():是否开启全景图自动旋转。
toggleDeviceOrientation():是否开启重力感应方向控制。
toggleFullscreen():是否开启全景图全屏。
toggleStereo():是否开启立体效果(可用于WebVR哦)。
zoom(level):设置缩放级别。
zoomIn():放大。
zoomOut():缩小。