最近在看设备传感器的API,固然也少不了研究一下让微信称神的“摇一摇”了。关于“摇一摇”的实现,网上不少资料因此不详细说了,但老是有布局、效果不全等各类问题,因此做为一名资深copypaster,代码确定是要贴的: 源码在此 html
手机扫二维码看看效果,支持Chrome、Safari、微信(新版):git
核心代码是这一段:github
this.deviceMotionHandler = function(eventData) { var acceleration = eventData.acceleration; var curTime = new Date().getTime(); //检测频率:每100ms一次 if ((curTime - that.last_update) > 100) { var diffTime = curTime - that.last_update; that.last_update = curTime; that.x = acceleration.x; that.y = acceleration.y; that.z = acceleration.z; var speed = Math.abs(that.x + that.y + that.z - that.last_x - that.last_y - that.last_z) / diffTime * 10000; if (speed > that.SHAKE_THRESHOLD) { //do something that.shakeAudio.play(); //摇一摇音效 window.navigator.vibrate(200); //振动效果 that.shakeEffect.className = 'shake-box shaking'; //摇一摇图片动态 clearTimeout(shakeTimeout); var shakeTimeout = setTimeout(function() { that.shakeEffect.className = 'shake-box'; },4000); } that.last_x = that.x; that.last_y = that.y; that.last_z = that.z; } };
原理: 以100ms的间隔去扫描加速度计,当检测到加速度发生突变(变化率大于阀值)时,就能够认为此时在甩动手机。由公式能够看到,这里检测的是3个方向的加速度,因此不管往什么方向甩均可以触发摇一摇效果。web
注意点: 这里加了一个摇一摇的音效,移动端关于音频的坑太多,想必各位也是碰到很多。本次的坑是即便调用了play也没法播放,解决办法是让用户操做第一次播放或者加载,具体来讲就是绑定一个事件,以下。并且加载须要必定时间,这里原本应该再作缓冲处理,但我没有,因此第一次播放会有很明显的延迟。微信
window.addEventListener('touchstart',function () { if ( !shake1.audioLoaded ) { shake1.shakeAudio.load(); //load事件必须由用户触发 shake1.audioLoaded = true; } }, false);
布局方面: 布局方面尝试使用了CSS3的弹性盒子,可是万万没想到先进的X5内核竟然仅支持 display: -webkit-box; 因此这里须要多写一套兼容的样式。动态效果原本想用 transition 凑合一下,看了效果仍是过不了本身这关,最后仍是换成 animation 实现。transition的问题是撑开和收缩时边框的行为不对,用动画就比较好解决了。布局须要注意的是:背景图的上半部须要多加一层嵌套实现自适应。另外,微信的边框还有阴影,这些细节我们暂时先忽略了。HTML结构以下:ide
<div class="bodymask"><h2>准备好了吗?<br />点击屏幕开始"摇"!</h2></div> <div class="shake-box"> <div class="shake-upside"> <div class="shake-upside-inner"></div> </div> <div class="shake-backimage"> <a href="http://www.cnblogs.com/qieguo/"><img id="id-shake-image" src="source/000.png"/></a> </div> <div class="shake-downside"></div> </div>
以上实现了“摇一摇”效果,但以楼主固然不会到此为止。下面是楼主失败而有益的探索(“有益”二字可无视)布局
其实楼主是一个吃饭都不想动手的重度懒癌患者,拿着手机看得正爽的时候还要我伸出中指去点击屏幕或者滑动,真的好累啊。。。特别是在躺着的时候,拇指是一个受力点,既要支撑手机还要伸出去滑动屏幕,很不天然。因此,为何不能甩一甩就翻页呢? 好比说下面的场景:测试
分析:动画
这个需求貌似很简单的样子,加速度是有方向的,直接判断x轴加速度正负不就能判断是左甩仍是右甩了吗? 摇一摇的代码稍微改改貌似就能实现了呢,窃喜~~~然而,理想老是太丰满,而现实却太骨感。不管咱们往哪一个方向甩动,最后要中止仍是须要加一个阻力,因此一次甩动过程当中至少有一次加速度方向的变化。请注意,这里有个“至少”,由于有时候咱们要向左甩的时候,可能开始会先向右退一点才左甩的;在刹停的时候也颇有可能刹过头了,这里加速度就会有一个抖动。this
想象老是没说服力,咱们仍是看看数据吧。固然这里先利用摇一摇相似的筛选规则来去掉非甩动的动做。当检测到加速度发生突变(变化率大于阀值)时认为发生了一次甩动,这时候输出 x 轴的加速度值来看看,扫描频率设置为100ms的时候数据以下:
上面分别是左甩和右甩时候的数据,根据这个数据特色,判断每个周期的第一个符合条件的加速度正负就能够判断甩动的方向了,楼主这里定义每一个甩动周期为1s。
var speed = Math.abs(that.x + that.y + that.z - that.last_x - that.last_y - that.last_z) / diffTime * 10000; if (speed > that.SHAKE_THRESHOLD) { if ((curTime - that.last_catch) > 1000) { if (that.x > 5) { output.innerHTML += '右甩x:' + that.x + '<br/>'; //加速度向右,右甩 that.last_catch = curTime; } else if( that.x < -5) { output.innerHTML += '左甩x:' + that.x + '<br/>'; //加速度向左,左甩 that.last_catch = curTime; } } }
理论上这个是能够筛选掉不适合的加速度数据了,测试以下:
看起来像是获得了准确的结果,但不一样人有不一样的习惯、力度,上面的方法并不能很好的获得最准确的办法。
更为准确的办法应该是求出x的位移,再加上 x轴加速度变化判断是否甩动,二者结合就能够很好的判断甩动方向了。这里位移只要求能判断左右,因此直接用高中物理的公式便可。可是,在测试了 n 次以后,我才开始想,这个需求是真实存在的吗?仍是说只存在个人臆想里面? 忽然想起红衣教主的话,不少人啊都是掌握一门技术以后呢就会把这个技术包装成一个产品,还会强行为这个产品适配不少需求,但这些需求都是YY,都是伪需求!
真理!老周这一针见血啊!
不过呢,加速度计和陀螺仪仍是很是好玩的东西,好好利用它们仍是能够实现不少有趣的东西,好比说这个:AIWI使用手机玩体感游戏。
只要你能利用加速度计和陀螺仪计算出空间中的运动轨迹,那这一切都好办了,不过要获得比较好的精度可不能用高中物理那种简单的时域积分哦,这个楼主就不敢强行装逼了,有兴趣的同窗自行搜索哈。
以上,这一篇都实在太水了,仍是放图吧。
(图片出处:小周同窗,转载请注明)
原创文章,转载请注明出处!本文连接:http://www.cnblogs.com/qieguo/p/5448786.html