最近在開發一個視頻播放器項目,須要隱藏 video 標籤,使用 canvas 本身作渲染。結果在點按鈕播放視頻的時候發現 zepto touch 模塊不能用了。canvas
看了一下錯誤提示,發現手機瀏覽器只容許用戶操做打開 video,換句話說無論你最終是哪一個函數執行了 video.play(),你的調用棧上溯到最開始必定是一個 DOM 元素的 UI 事件回調。瀏覽器
可是zepto touch 模塊是這麼封裝 tap 事件的:異步
tapTimeout = setTimeout(function() { // trigger universal 'tap' with the option to cancelTouch() // (cancelTouch cancels processing of single vs double taps for faster 'tap' response) var event = $.Event('tap') event.cancelTouch = cancelAll // [by paper] fix -> "TypeError: 'undefined' is not an object (evaluating 'touch.el.trigger'), when double tap if (touch.el) touch.el.trigger(event) // trigger double tap immediately if (touch.isDoubleTap) { if (touch.el) touch.el.trigger('doubleTap') touch = {} } // trigger single tap after 250ms of inactivity else { touchTimeout = setTimeout(function(){ touchTimeout = null if (touch.el) touch.el.trigger('singleTap') touch = {} }, 250) } }, 0)
使用 setTimeout 異步執行函數,致使調用棧被清空了,系統判斷的時候天然不會認爲是用戶操做致使的 video.play()。ide
那麼比較粗暴的解決方法就是修改 zepto 代碼,把 tap 事件的激發動做從異步回調中移出來同步執行,具體的說就是這三行:函數
var event = $.Event('tap') event.cancelTouch = cancelAll if (touch.el) touch.el.trigger(event)
由於 tap 事件是沒有什麼延時的,因此直接移出來不會有什麼影響,若是是延時事件就很尷尬了,暫時還想不出來什麼解決方法。lua