在一些全景展示类应用中,经常需要对采集到全景照片进行展示,一般情况下,可以通过制作人员使用pano2vr进行数据处理(教程可参见:实战!使用pano2vr生成html5全景页面),将处理好的数据发布至静态服务器,再关联相应位置即可完成全景展示(详情见基于Leaflet的全景综合展示实战)。
以上这种方式可用于素材不多,发布后不会轻易变化,而且对制作时间没有精确时间要求的场景。而且应用多依赖于人工操作,如果想直接对采集的全景照片进行直接展示的,可以采用什么方案呢?本文将介绍一种不依赖于人工的全景素材直接展示的解决方案。
Three.js是一个可以运行在浏览器端的3D引擎,可以创建多种三维场景,是webGL的一种丰富展示,通过控制相机、场景、材质、光照等信息来完成3D展示(Three.js的专业知识可以具体参考官网或者搜索引擎,本文不赘述)。
TPano基于Three.js可以直接对全景照片进行展示,无需任何人工处理,所见即所得,非常方便。下面将如何在TPano中集成全景进行简单阐述。
第一步、引入Three.js 和TPano.js 等信息
!--引入three.js--><scriptsrc="./three.js"></script><scriptsrc="../dist/tpano.js"></script><!--设备朝向控制器,不引入无法使用体感控制--><scriptsrc="./DeviceOrientationControls.js"></script><!--jquery框架,这里引入用来做一些其它的操作,TPano不依赖它,故你不需要可以不引入--><scriptsrc="./jquery-2.1.4.js"></script>
第二步、定义全景照片对象
letpanoPhoto= [ //全景照片数组,每项为一张照片 { url: 'pano/DSCN0007.JPG', name: '足球场入口', }, { url: 'pano/DSCN0009.JPG', name: '足球场' }, { url: 'pano/DSCN0013.JPG', name: '足球场坡道' }, { url: 'pano/DSCN0016.JPG', name: '湖边' }, { url: 'pano/DSCN0017.JPG', name: '图书馆旁' }, { url: 'pano/DSCN0018.JPG', name: '小公园' }, { url: 'pano/DSCN0019.JPG', name: '篮球场旁' }, { url: 'pano/DSCN0035_1.avi', type: 'VIDEO', name: '视频' }, ];
第三步、定义网页dom渲染节点
<bodyid="pano"><divid="load"><divid="load-bar-k"><divid="load-bar-x"></div></div></div><divid="controller-y"><divid="photo"onclick="switchPhoto()"class="item item-f"><imgsrc="./img/bar/photo.png"alt="照片"><divclass="point"></div></div><divid="gyro"onclick="switchGyro()"class="item item-f"><imgsrc="./img/bar/gyro.png"alt="体感"><divclass="point"></div></div><divclass="item item-s"onclick="hidefunction()"><imgsrc="./img/bar/function.png"alt="功能"></div></div><divid="photo-box"><div><divhiddenclass="photo-box-div"id="example"><imgclass="photo-box-img"src=""alt=""><pclass="photo-box-p">示例</p></div></div></div></body>
第四步、开启TPano加载
vartpano=newTPano({ el: 'pano',//照片查看器根节点dom的idphoto: panoPhoto, photoLoad: function (e) { console.log(e); closeLoadAnimate(); if (gi==0) { //第一张照片加载完毕//解锁控制器controllerLock=true; //6秒后隐藏功能键setTimeout(() => { hidefunction(); }, 6000); } gi++; if (gi==panoPhoto.length) { //全部加载完毕//这个时间点开始加载相册,此功能未经后端优化的情况下加载的是原始照片,故非常的占用带宽,我们希望晚一些加载它cratePhoneBox(); photoBoxLock=true; } }, switchLoad: function (e) { console.log(e); switch (e.status) { case'loading': loadAnimate(); break; case'end': closeLoadAnimate(); break; default: alert('加载出错'); break; } }, gyroSport: function (e) { if (!e&&!msgStatus) { msgStatus=true; alert('设备可能不支持陀螺仪,或者您没有启用https。多数浏览器安全策略只对启用了https的网站提供陀螺仪服务。'); } }, hotspot: [ //全景照片上的热点 { source: '足球场入口',//此热点放置在哪张全景照片上position: {//热点所在的位置x: 496.89276177820193, y: -45.470141450240746, z: 15.7856948039098 }, imgUrl: './img/foot.png', jumpTo: '足球场'//热点点击后跳往何方 }, { source: '足球场', position: { x: -336.2550875236564, y: -14.322516705554547, z: -369.0878923870561 }, imgUrl: './img/foot.png', jumpTo: '足球场坡道' }, { source: '足球场坡道', position: { x: 9.916517848911612, y: -73.87696480294954, z: -493.83818114696464 }, imgUrl: './img/foot.png', jumpTo: '湖边' }, { source: '湖边', position: { x: 54.089284409982234, y: -25.567089425803836, z: 495.95622841487307 }, imgUrl: './img/foot.png', jumpTo: '图书馆旁' }, { source: '足球场坡道', position: { x: -496.45652472791767, y: -25.137666788574762, z: -48.767873292494635 }, imgUrl: './img/foot.png', jumpTo: '图书馆旁' }, { source: '图书馆旁', position: { x: -22.146984058775047, y: -53.75657318610189, z: 495.5786184825647 }, imgUrl: './img/foot.png', jumpTo: '小公园' }, { source: '小公园', position: { x: 470.9682632032511, y: -66.67077805764235, z: 153.04203582643925 }, imgUrl: './img/foot.png', jumpTo: '篮球场旁' }, { source: '篮球场旁', position: { x: -452.2504972710258, y: 7.828318511793819, z: 211.56713992810768 }, imgUrl: './video.png', jumpTo: '视频' } ], DeviceOrientationControls: false,//设备朝向体感控制,默认关闭rotateAnimateController: true,//镜头自转debug: true,//调试模式 });
第五步、展示效果如下
全景展示1
六、总结
以上展示了如何使用TPano进行全景素材的展示。基于Three.js即可完成图片和视频的展示而不需要进行图片切片处理,从而提高了数据从采集到发布的效率。
TPano框架展示地址:https://gitee.com/push_0x57df/TPano,这是gitee上分享的框架地址,感兴趣的朋友可以clone到本地进行调试。
留一个思考的问题:全景照片一般都很大,如果直接展示不仅影响速度,而且会加大服务器的带宽压力,那么如何解决全景的快速可视化呢?欢迎交流。