刚开始的处理方式是,摇晃过程当中不作任何处理,但后来反馈说这种效果很差,好像就没有摇动同样,若是声音也不响的话,就真的和什么都没发生同样。javascript
后来想了想,加入摇晃过程动画,就像微信的摇一摇同样,摇晃过程当中,会有上下移动的动画,这里加入了周围金币作跳跃运动的动画。css
摇晃灵敏度是个不太好控制的量,即要求不是很灵敏,好比,不能稍微碰一下就摇晃了,也不能使劲摇才能摇中,这就须要对X、Y、Z轴上的加速度进行合理利用,这里是几种网上常见的处理方式:html
Math.abs( x + y + z - lastX - lastY - lastZ ) / diffTime * 10000
这种方式在网上最为常见,大多数的示例都采用的该方法。后来看到有人评论此方法可能致使摇一摇并不特别灵敏,好比x为正、y为负,就可能出现抵消的状况。html5
Math.abs(x-lastX) > speed || Math.abs(y-lastY) > speed
该方法也是shake库采用的计算方式,不过,该库的计算方式覆盖的更全面一些,也包括了斜向摇晃的判断,该库有近1000个start,使用人数也较多:java
this.options.threshold = 15; deltaX = Math.abs(this.lastX - current.x); deltaY = Math.abs(this.lastY - current.y); deltaZ = Math.abs(this.lastZ - current.z); if (( (deltaX > this.options.threshold) && (deltaY > this.options.threshold)) || ( (deltaX > this.options.threshold) && (deltaZ > this.options.threshold) ) || ( (deltaY > this.options.threshold) && (deltaZ > this.options.threshold)) ) {}
Math.sqrt( ( x - lastX ) * ( x - lastX ) + ( y - lastY ) * ( y - lastY ) + ( z - lastZ ) * ( z - lastZ ) ) / diffTime * 10000
这种方式相似于求三维空间中任意两点的距离
,而后经过距离除以时间,获得速度的变化率,在摇晃过程当中摇晃的速度知足条件就表示中奖了。目前来看,这种方式更加科学一点,由于它更能体现出摇一摇的实际情景:摇的快一点,就能摇一摇。android
刚开始的时候采用的是第一种计算方式,计算在这一段时间内的平均值,可是在使用的过程当中发现并非很好用,设置的值过小就会比较灵敏,太大又不太灵敏,老是找不到一个合适的值知足条件。后来改用第三种方式,能够获得良好的摇一摇体验。ios
这个功能在业务中并无加入,考虑后期优化的时候添加进去,在用户摇晃的过程当中也能震动,能够很大的提高用户体验,让手机震动,经过以下API:css3
navigator.vibrate
var supportsVibrate = "vibrate" in navigator;
navigator.vibrate(2000) // 震动2s window.navigator.vibrate([ 100,30,100,30,100,200,200,30, 200,30,200,200,100,30,100,30,100]); // 震动出莫尔斯电码的"SOS"效果 // 取消震动,赋值0或空数组便可 navigator.vibrate(0)
经过CanIuse查看支持状况,支持android4.4,ios不支持。git
这里是一篇比较完善的关于HTML Audio的说明克服 iOS HTML5 音频的局限。github
大概总结几点:
iOS3中,移动版safari中就已经引入HTML音频
iOS6中,Apple增长了Web Audio API的支持
备注:到目前为止,iOS版本分布以下,因此,目前使用HTML音频基本没有兼容问题。
目前主要支持四种格式:MP三、OGG、WAV 和 AAC。
Ogg Vorbis | WAV | PCM | AAC | |
---|---|---|---|---|
Internet Explorer 9 | X | X | ||
Firefox | X | X | ||
Chrome/Safari/移动版 Safari | X | X | X |
为了涵盖全部浏览器,最好是让全部的视频流都具备 Ogg Vorbis 和 AAC 两种格式。
为何没有包括 MP3?MP3 在进行商业传播时须要支付繁重的版税。
Ogg Vorbis 之因此压倒性地得到了个人喜好是由于它是开源的、无专利费而且免版税的。不过,只有 Firefox 支持它。
移动版safari一次只能播放一个单音频流。移动版 Safari 中的 HTML5 媒体元素都是单例的,因此一次只能播放一个 HTML5 音频(和 HTML5 视频)流。Apple 为这一局限作过解释,但咱们推断这是为了减小数据费用(这也是大多数 iOS HTML5 其余局限的缘由所在)。
在移动版 Safari 中加载的页面上,不能自动播放音频文件。音频文件只能从用户触发的触摸(单击)事件加载。preload、autoplay会忽略。
在初始化一个新的音频流时会有几秒的延时,这是由于 iOS 须要实例化一个新的音频对象。
解决方案
当用户触摸屏幕的时候,便会加载音频,而后在摇晃手机时进行播放。
var shakeAudio = new Audio(); shakeAudio.preload = 'auto'; shakeAudio.src = 'xx'; document.body.addEventListener('touchstart', () => { shakeAudio.load(); });
使用audio sprite。
audio.sprite能够将多个音频合成一个音频,就像css sprite同样。
原理很直观。您须要存储每一个 sprite 的数据:开始点、结束点(或长度)和一个 ID。当您想要播放某个 sprite 时,须要将此音频流的 currentTime 设为开始位置并调用 play()。
var spriteData = { meow1: { start: 0, length: 1.1 }, meow2: { start: 1.3, length: 1.1 }, whine: { start: 2.7, length: 0.8 }, purr: { start: 5, length: 5 } }; audioSprite.currentTime = spriteData.meow2.start; audioSprite.play();
这种方式能够解决单个音频与切换延迟的问题,由于只有一个音频加载,这也削减了HTTP请求。
清注意,更改 currentTime 并非百分百正确的。将 currentTime 设为 6.5,而实际获得的倒是 6.7 或 6.2。每一个 A sprite 之间须要少许的空间,以免寻找到另外一个 sprite 的尾部。添加这个空间会增长少量延时,若是流寻找到 6.4,而 sprite 开始于 6.8 秒。
在访问任何 audio sprite 以前,务必确保整个音频流已加载,由于若是音频流没有彻底加载,那么在想要访问已加载的流的任何一个部分时,那么这个流须要进行缓冲,并且还会在流加载过程当中发生延时。
注意,音频资源放到服务器可能也不会成功!
这是Chromium的一个bug:https://bugs.chromium.org/p/chromium/issues/detail?id=584562。
备注:我在实际测试的出现问题,currentTime没法设置,一直都是0,即时赋值为3,但打印出来后依然为0,致使音频不能切换。
测试地址:http://img.youthol.top/audioTest-1.html
这个问题尚未找到具体缘由。应该和服务器设置有关,该问题已经浪费了好长时间去搜索,目前还没找到更具体的缘由。
在项目中有一个体验须要优化,若是活动在晚上12点开始,用户在12点以前进来,此时是不能参加的,提示活动时间还不到,可是若是到12点了呢?用户必须退出去而后在进来,这样才能看到最新的状态?
这样体验会差一点,最好的方式是:到达了12点,数据自动更新。用户能够直接参与抽奖!
为了实现这一个效果,采用的思路是:用户刚进入页面的时候会有一个时间戳,而后我拿到该时间戳进行解析,获取当天的时间属性(年月日),而后经过new Date()
建立一个次日的凌晨时间,此时,用该时间与页面请求的时间作diff,利用setTimeout
进行diff时间的倒计时,倒计时结束,自动执行数据更新。
这种思路在android上是没有问题的,可是测试时发如今ios上不会更新数据,后来定时,是获取时间时有问题:
原本我是经过new Date("2016.12.27")
这样的方式在chrome的测试控制台中测试的,能够拿到当天凌晨时间,因而便拿该时间去用,可是该时间在safari中会出错:
new Date("2016.12.27") // Invalid Date new Date("2016.12.27").getTime() // NaN
这就遇到了一个好玩的事情,那safari下支持什么样的时间格式呢?下面便进行一些测试:
safari:在safari浏览器中处理时间会产生很是有意思的效果,好比:
new Date("2016.12.27") // Invalid Date new Date("2016-12-27") // Tue Dec 27 2016 08:00:00 GMT+0800 (CST) new Date("2016/12/27") // Tue Dec 27 2016 00:00:00 GMT+0800 (CST)
chrome:可是在chrome上,咱们测试一下:
new Date("2016.12.27") // Tue Dec 27 2016 00:00:00 GMT+0800 (CST) new Date("2016-12-27") // Tue Dec 27 2016 08:00:00 GMT+0800 (CST) new Date("2016/12/27") // Tue Dec 27 2016 00:00:00 GMT+0800 (CST)
.
点的日期形式在safari上是不支持的
-
短线的日期形式返回值相同
/
斜杠的日期形式返回值也相同
另一个更神奇的地方是,一样是ISO 8601日期格式形式,safari也获取不到:
new Date("2016-12-27 12:34:25") // Invalid Date
stackoverflow有人提这个问题,这是一个回答:并非全部的浏览器都支持上面的形式,最好的方法就是经过(
-
,`,
:`)分隔符把日期分离,而后分别传给Date构造器:
var arr = "2010-03-15 10:30:00".split(/[- :]/), date = new Date(arr[0], arr[1]-1, arr[2], arr[3], arr[4], arr[5]); console.log(date); //-> Mon Mar 15 2010 10:30:00 GMT+0000 (GMT Standard Time)
这样全部的浏览器都运行正常。不过,须要注意的是,月份要减1,GMT的时间月份0表示1月份。
一样,根据这篇文章:JavaScript new Date() NaN on iPhone,能够经过以下方式,也能够获取浏览器一致的效果:
mm/dd/yyyy hh:mm:ss if (app.isAppleDevice()) { var dateParts = myDate.substring(0,10).split('-'); var timePart = myDate.substr(11); myDate= dateParts[1] + '/' + dateParts[2] + '/' + dateParts[0] + ' ' + timePart; }
关于时间问题坑仍是不小的,红宝书上对时间的描述也较多,也可参考。
在平时的项目中,通常要求有较快的用户反馈,可是在摇一摇项目中,有一些小的交互需求须要注意。
第一个就是该总结刚开始说的,延迟出现抽奖结果,这样更符合用户体验。摇一摇立马弹出反而更显突兀。
在业务中,有一个滚动公告需求,刚开始滚动公告采用setInterval的方式进行,可是当把切换其余浏览器tab一段时候后再次回来,发现公告是快速的滚动到某一位置。
缘由是setInterval在窗口退到后台时依然会执行。解决这个问题就须要requestAnimationFrame了。
虽然requestAnimationFrame不能够直接设置时间间隔,但能够经过时间判断来完成:
let lastTime = 0; const scroll = () => { const now = Date.now(); if ( now - startTime > during ) { startTime = now; this.shakeScrollCurrent--; this.showNoticeList = true; // 若是滚动到头了,此时会从新进入滚动 // 防止在切换的过程当中出现动画,此时须要先把动画去除,而后在进行数量重置 if ( ( this.shakeScrollCurrent ) % ( prizesLength + 1 ) === 0 ) { this.showNoticeList = false; this.shakeScrollCurrent = 0; } } window.requestAnimationFrame( scroll ); } window.requestAnimationFrame( scroll );
从中能够看出android低版本(4.3)及如下是不支持该属性的,须要对此进行兼容,能够参考以下:
CSS3动画那么强,requestAnimationFrame还有毛线用?
window.requestAnimationFrame = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function ( callback, element ) { var currTime = new Date().getTime(); var timeToCall = Math.max(0, 16.7 - (currTime - lastTime)); var id = window.setTimeout(function() { callback(currTime + timeToCall); }, timeToCall); lastTime = currTime + timeToCall; return id; }
function (callback, element) { var start, finish; window.setTimeout(function () { start = +new Date(); callback(start); finish = +new Date(); self.timeout = 1000 / 60 - (finish - start); }, self.timeout); };
摇一摇过程并不复杂,其实像这种活动更重要的是如何提高用户体验,好比在项目中发现,有的手机其支持加速事件,可是摇晃过程没有任何的反应。好比Android 6.0; PLK-AL10(HUAWEI)
,若是有这同款手机的童鞋能够试一试。说这些是提醒有作相关活动的童鞋,能够在项目中添加统计代码,上报该手机支持仍是不支持摇一摇,若是不支持也能够加入预警,这样能够及时获得反馈。若是不支持,能够考虑添加其余途径也能参与活动。
关于音频的问题,是须要继续调研下的,若是你们知道缘由麻烦也告诉我哦,查找了好几天了。。。