剛開始的處理方式是,搖晃過程當中不作任何處理,但後來反饋說這種效果很差,好像就沒有搖動同樣,若是聲音也不響的話,就真的和什麼都沒發生同樣。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)
,若是有這同款手機的童鞋能夠試一試。說這些是提醒有作相關活動的童鞋,能夠在項目中添加統計代碼,上報該手機支持仍是不支持搖一搖,若是不支持也能夠加入預警,這樣能夠及時獲得反饋。若是不支持,能夠考慮添加其餘途徑也能參與活動。
關於音頻的問題,是須要繼續調研下的,若是你們知道緣由麻煩也告訴我哦,查找了好幾天了。。。