微信小程序Video組件實踐總結

我司微店+小程序最近有須要在商品詳情裏面添加視頻的功能,故使用了微信官方 Video組件,在使用過程當中遇到了一些問題,有些問題特別坑,我以爲有必要總結一下,分享出來供有這方面需求的同行參考,本篇文章我主要講解最終我使用的兼容性比較好的方案,但願能幫助有須要的童鞋。

在我使用video組件的過程當中,主要碰到如下問題:html

  • 佈局表現不一致
  • wifi下自動播放,視頻播放黑屏(安卓常見)
  • 視頻列表不能隨頁面滾動
  • 視頻全局播放,點擊返回按鈕,佈局位置異常
  • 視頻每次都須要從新加載

示例源碼ios

UI佈局

咱們要實現的佈局小程序

  • video上面有個覆蓋video的圖片,在圖片上有個控制播放的按鈕
  • video上面有視頻和圖片切換按鈕組合,視頻播放的時候該組合按鈕也必須存在

按照常規的寫法,咱們的代碼結構可能以下api

<view>
    <!-- 視頻 -->
    <video></video>
    <!-- 覆蓋視頻的圖片 -->
    <view>
        <image/>
        <!-- 播放按鈕 -->
        <view></view>
    </view>
    <!-- 底部視頻和圖片切換按鈕 -->
    <view></view>
</view>
複製代碼

而後經過圖片position:absolute絕對定位,z-index層疊上下文來完成佈局,這種方式在ios系統下表現還好,在一些安卓機上圖片和按鈕就會被video組件覆蓋,這是由於video組件是原生組件,使用上有一些限制,具體限制能夠看這裏微信官方文檔,在這裏主要影響咱們的緣由是,原生組件的層級是最高的,因此頁面中的其餘組件不管設置z-index爲多少,都沒法蓋在原生組件上。bash

幸虧,微信官方提供了cover-viewcover-image組件,能夠覆蓋原生組件上面。經過使用,咱們的方案以下:微信

<view>
    <video>
        <cover-view>
            <!-- 覆蓋圖片 -->
            <cover-image></cover-image>
            <!-- 播放按鈕 -->
            <cover-image></cover-image>
        </cover-view>
    </video>
</view>
複製代碼

播放功能

單個視頻,點擊播放

有關video組件播放的幾個配置,主要有網絡

  • src 要播放視頻的資源地址
  • autoplay 是否自動播放

另外,微信還提功能了const video = wx.createVideoContext()方法能夠得到一個video實例,經過video.play()方法來控制播放。ide

故有幾種方案:工具

第一種方案,拿到視頻地址後,經過setData方法更新video組件地址和自動播放爲true,該方法優勢是由組件自身控制開始播放時間,基本不會存在黑屏或者視頻加載出來不播放的狀況,但缺點是切換到其它頁面再回來,每次都須要從新加載視頻,性能和體驗上不是很好。佈局

<!--方案一-->

<!--js-->
this.setData({
    src:url,
    autoplay:true
})
<!--html-->
<video src="{{src}}" autoplay="{{autoplay}}"></video>

複製代碼

第二種方案,經過api控制,存在的問題就是視頻播放的時機,由於視頻地址加載是須要時間的,若是咱們在頁面一渲染後就點擊播放按鈕,此時若是視頻還未加載完,直接調用videoContext.play()方法可能會失效,故咱們需應該等待視頻加載完以後,才調用play()方法,這裏採用的是setData的回調方法裏面去調用play()方法開啓播放,另外還能夠經過pause()暫停,stop()中止等方法來控制視頻播放狀態。這種方案能夠只需加載一次視頻,以後播放無需從新加載,用戶體驗較好,另外對於沒法控制播放時機問題作了處理,基本不會出現黑屏的狀況

<!--方案一-->

<!--js-->
data:{
    autoplay:false
}
const { videoContext } = this.data;

<!--視頻播放,關鍵代碼-->
this.setData({
    autoplay:true,
    url:videoUrl
},()=>{
    videoContext.play()
})
<!--html-->
<video src="{{url}}" autoplay="{{autoplay}}"></video>
複製代碼

單個視頻,wifi下自動播放

微信提供判斷網絡環境的api,經過api判斷,若是是wifi下,就主動調用videoContext.play()方法。

wx.getNetworkType({
        success(res) {
            const networkType = res.networkType;
            if (networkType === 'wifi') {
                that.videoPlay();
            }
        },
    });
    
videoPlay(){
    this.setData({
        autoplay:true,
        url:videoUrl
    },()=>{
    videoContext.play()
    })
}
複製代碼

視頻不在可視範圍,中止播放

微信提供IntersectionObserver對象,用於推斷某些節點是否能夠被用戶看見、有多大比例能夠被用戶看見,之前判斷元素是否在視圖內,咱們經常使用的是getBoundingClientRect,該方法在微信環境也能使用,但該方法由於須要計算元素位置,引發頁面重繪,比較影響性能。而IntersectionObserver是原生本身判斷位置,不會有相關問題,能夠經過這個api來監聽元素位置,從而控制是否播放。

wx.createIntersectionObserver(that)
    .relativeToViewport()
        .observe('.video--wrap', res => {
            if (res && res.intersectionRatio > 0) {
                that.videoPlay();
            } else {
                that.videoPause();
            }
        });
複製代碼

視頻靜音播放

能夠經過變動muted這個屬性來控制視頻是否靜音,好比一開始默認靜音,點擊音量按鈕開啓聲音這個功能。

data:{
    muted:true //初始爲true,靜音
}
methods:{
    handleMuted(){
        this.setData({
            muted:false
        })
    }
}


複製代碼

視頻列表

一開始我是用過wx:for列舉視頻播放組件,子組件播放,觸發一個事件,父組件監聽子組件事件,更新視頻列表值,而後子組件監聽屬性變化來更新播放狀態的,該方案在ios上表現不錯,但是放在安卓上,頁面居然不能滾動了,後面經過查閱資料,video列表組件不能直接像普通圖片列表同樣,真正的方案是須要用視頻首幀圖片作列表,而後點擊首幀圖片,跳轉到一個新頁面,或者一個蒙層播放視頻。

小程序左滑右滑實現

咱們需求上還有左右滑切換圖片和視頻顯示的功能,這須要經過監聽touchstarttouchmove來判斷手機滑動方向,從而切換視頻和圖片的顯示位置。

touchstart: function(e) {
        this.setData({
            startX: e.changedTouches[0] && e.changedTouches[0].clientX,
            startY: e.changedTouches[0] && e.changedTouches[0].clientY,
        });
    },
touchmove: function(e) {
        var that = this,
        startX = that.data.startX, //開始X座標
        startY = that.data.startY, //開始Y座標
        touchMoveX = e.changedTouches[0].clientX, //滑動變化座標
        touchMoveY = e.changedTouches[0].clientY, //滑動變化座標
    },
//根據起點和終點返回方向 1:向上,2:向下,3:向左,4:向右,0:未滑動
GetSlideDrection: function(startX, startY, endX, endY) {
    var dy = endY - startY;

    var dx = endX - startX;

    var result = 0;

    //若是滑動距離過短

    if (Math.abs(dx) < 2 && Math.abs(dy) < 2) {
        return result;
    }

    var angle = this.GetSlideAngle(dx, dy);

    if (angle >= -45 && angle < 45) {
        result = 4;
    } else if (angle >= 45 && angle < 135) {
        result = 1;
    } else if (angle >= -135 && angle < -45) {
        result = 2;
    } else if ((angle >= 135 && angle <= 180) || (angle >= -180 && angle < -135)) {
        result = 3;
    }

    return result;
    },
GetSlideAngle: function(dx, dy) {
    return (Math.atan2(dy, dx) * 180) / Math.PI;
},

複製代碼

以上方案均可以經過小程序代碼片斷進行查看

點擊查看方案

調試

開發者工具和真機表現差別很大,故在開發者工具上開發完以後,須要多在不一樣真機上進行調試。

總結

實際我在開發中碰到的問題還挺多,小程序video組件坑仍是挺多的,我沒有一一描述出來,若是你有碰到其它問題,歡迎留言評論,若是我曾經碰到過,或許可以提供一些意見,我寫這篇文章的目的就是讓更多的小程序開發者儘可能少踩坑,若是恰好可以幫助到你,感謝點贊支持!

相關文章
相關標籤/搜索