大家好我是张鹏辉(道长)人如其名,我是天桥上算命的,转发这条博文,接下来一个月会有意想不到的惊喜发生。最近微博上的全景图火了,所以决定实现一下。工程里面图片资源来自网络,如有侵权请联系我,马上删除当然实现的方式很多比如OpenCV、u3d等。这里提供三种方式实现:
先看下三种实现的效果:
第一种方式使用OpenGL来实现(上面gif图截取因为博客限制上传图片的大小,我压缩了,看起来有些卡其实很流畅的)可以看到支持旋转手机查看、或者拖动图片查看、可以看到右边中心部分有个指示器会随着角度变化而变化并且点击可以还原起始位置。
有些小伙伴懒得看原理,直接就想拿来用所以我先说集成方式吧!
首先我们需要了解全景图是什么东西,全景图是一种广角图。通过全景播放器可以让观看者身临其境地进入到全景图所记录的场景中去,通常标准的全景图是一张2:1的图像,其背后的实质就是等距圆柱投影。等距圆柱投影是一种将球体上的各个点投影到圆柱体的侧面上的一种投影方式,投影完之后再将它展开就是一张2:1的长方形的图像。比较常见的就是应用在地图上的投影。
得到全景图后那我们就需要展示了,看到旁边地球了吗?
怎么展示呢简单来说就是把全景图片整个贴到一个球体上。好了知道原理那我们就该考虑在android上怎么实现了,在android中绘制3d图形可以使用OpenGL (就不说OpenGL 基础了想看的自己百度一大堆资料)。
引用tim_shadow大佬的关于全景图一篇文章介绍在OpenGL ES中基本上所有的立体图像都是通过一个个的小三角形拼接而成我们知道球面上面的每一个点(P(x,y,z))都会满足方程组(球的极坐标方程):x = r * sin(a) cos(b)y = r * cos(a)z = r * sin(a)sin(b)其中 r为球的半径,a为线段 OP与 z轴正方向所夹角,b为 OP在xoy平面的投影 OP‘ 与x的正方向所夹角
纹理和图片绑定绘制到屏幕上
第一想到的就是重力感应传感器,可是只能获得我们向那个位置偏移的方向,显然不可能满足我们旋转的需求,使用陀螺仪传感器。陀螺仪就是内部有一个陀螺,它的轴由于陀螺效应始终与初始方向平行,这样就可以通过与初始方向的偏差计算出实际方向。陀螺仪对设备旋转角度的检测是瞬时的而且是非常精确的。
首先注册陀螺仪传感器根据具体需要自己设置灵敏度,当然越灵敏,越耗电。
我这里为了测试设置了SENSOR_DELAY_FASTEST,实际使用建议用SENSOR_DELAY_GAME
当传感器的值发生变化时,例如磁阻传感器方向改变时会调用OnSensorChanged(). 当传感器的精度发生变化时会调用OnAccuracyChanged()方法。
从 x、y、z 轴的正向位置观看处于原始方位的设备,如果设备逆时针旋转,将会收到正值;否则,为负值得到两次检测到手机旋转的时间差(纳秒),并将其转化为秒将手机在各个轴上的旋转角度相加,即可得到当前位置相对于初始位置的旋转弧度,将弧度转化为角度
每次获得角度数据后只需要y,x的值计算位移的值
因为全景图上下旋转会翻转整个图所以我这里设置了上下只能偏移50f,如果不限制你可以去掉
加入手势这里没什么好说的了,就是重写onTouchEvent()方法。这里唯一要注意的就是,当手指点击屏幕的时候要关闭陀螺仪传感器的监听不然会引起冲突。当手指离开屏幕,重新监听陀螺仪传感器。和上面也一样只是这里换成获取手指偏移角度,而不是传感器的数值,直接看代码。
指示器这里弄了一个角标指示当前在全景图的角度,并且点击还原起始角度。可以想象同样是获取角度,我们直接放在全景图改变的地方,让指示器一起改变,而我们改变的地方只有2个陀螺仪和拖动屏幕。我这里指示器放了一张图也就是一个 ImageView 控件
1.为指示器加入动画跟随全景图一起转
2.点击指示器还原起始位置
看代码:
第二种也就是谷歌官方为移动平台下VR解决方案,有兴趣的可以点开下面链接玩玩,我们只使用其中全景图模块。
考虑到在多种机型兼容性,还有原生WebView的一些坑,我这里使用腾讯的X5内核的WebView。
你可以使用js交互将你的地址传到HTML上
直接上代码了:
很简单就是把系统的WebView换成Tencent_Webview其他类似
最后附上插件的可配置参数:
三种方式都实现完了,不用担心今天所有代码都会放在GitHub上。三种方式具体你使用哪种我还是没有推荐的这里只是一张图,你可以多张图实现来完成简单的全景街景功能!点击图片某个区域,跳转到下一个街景的图,包括百度地图里面也是一张张全景图拼接而成。