調試手記:zepto touch 模塊與移動瀏覽器 media 標籤的不兼容,以及解決方法

問題描述

最近在開發一個視頻播放器項目,須要隱藏 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

相關文章
相關標籤/搜索