天天看點

uni-app App 下內建 xgplayer

uni-app APP 下內建 xgplayer

uniapp 使用 uni-upgrade-center

前言

如果是 Web 下內建 xgplayer 是很友善的,直接按照官方文檔就可以,這裡就不做讨論。

之是以是講 app 下,原因在于 uni-app app 下調用這類 JS 庫涉及到操作 dom 的就需要特殊出來。

在最開始按照 web 方式內建進來一直報錯,一點頭緒沒有,經過幾天摸索加上咨詢找到了一些方式。

主要的解決方案有以下兩張:

1、uni-app 的 renderjs 實作

2、webview 實作

一、webview

web-view 作為一個 web 浏覽器元件,可以用來承載網頁的容器,會自動鋪滿整個頁面。(官方文檔)

從上面這句話的介紹可以看出:

  1、用來承載網頁

  2、會自動鋪滿

基于這兩個特點,要實作的話基本思路是:

  a、建立一個 html 頁面,在這裡使用 xgplayer

  b、建立一個vue或者nvue頁面,用 web-view 加載這個 html 頁面

按照這個思路主要代碼如下:

xgplayer.html

<!DOCTYPE html>  
<html>  
  <head>  
    <meta charset="utf-8">  
        <meta name=viewport content="width=device-width,initial-scale=1,maximum-scale=1,minimum-scale=1,user-scalable=no,minimal-ui">  
        <meta name="referrer" content="no-referrer">  
    <title></title>  
    <!-- <script src="js/uni.webview.1.5.2.js" charset="utf-8"></script>  -->
    <style type="text/css">  
      html, body {width:100%;height:100%;margin:auto;overflow: hidden;background-color: #000000;-webkit-user-select: none; user-select: none;}  

    </style>  
    <!-- uni 的 SDK,必須引用。 -->  
    <script type="text/javascript" src="//js.cdn.aliyun.dcloud.net.cn/dev/uni-app/uni.webview.0.1.52.js"></script>
  </head>  
  <body>  
    <div id="mse"></div>
    <script src="//unpkg.byted-static.com/[email protected]/browser/index.js" charset="utf-8"></script>
            let url = getQueryVariable('src');  

            let player = new Player({
                 "id": "mse",  
                 "url": url,  
                 "playsinline": true,  
                 "width":"100%",
                 "height":"181px",
                 "autoplay": false,  
                 "whitelist": [''],  
                 // "danmu": { 
                 //   "comments": [  
                 //     {  
                 //       "duration": 15000,  
                 //       "id": '1',  
                 //       "start": 3000,  
                 //       "txt": '長彈幕長彈幕長彈幕長彈幕長彈幕',  
                 //       "style": {  //彈幕自定義樣式  
                 //         "color": '#ff9500',  
                 //         "fontSize": '17px',  
                 //         // "border": 'solid 1px #ff9500',  
                 //         "borderRadius": '50px',  
                 //         "padding": '5px 11px',  
                 //         "backgroundColor": 'rgba(255, 255, 255, 0.1)'  
                 //       }  
                 //     }  
                 //   ],  
                 //   "area": {  
                 //     "start": 0,  
                 //     "end": 1  
                 //   }  
                 // },  
             });  

             //擷取url參數  
             function getQueryVariable(variable)  
             {  
                var reg = new RegExp('(^|&)' + variable + '=([^&]*)(&|$)', 'i');  
                var r = window.location.search.substr(1).match(reg);  
                if (r != null) {  
                   return unescape(r[2]);  
                }  
                return null;  
             }  

        </script>  
  </body>  
</html>      

xgplayer.vue

web-view 有兩種方式,直接 web-view 元件或者 plus.webview.create,這裡使用 plus.webview.create(對于使用 webview 元件,可以自行查找)

<template>
</template>

<script>
     export default {
         props:{
             src:{
                 type:String,
                 default:''
             }
         },
            data()  
            {  
                return{  
                    //視訊位址  
                    // src:'http://vd2.bdstatic.com/mda-jmawcmkjagd8je0u/mda-jmawcmkjagd8je0u.mp4'   
                }  
            },  
            onBackPress()
            {  
                //退出頁銷毀播放器  
                uni.$xgplayer.close()  
            },  
    
            mounted()  
            {  
                this.xgplayer()  
            },  
    
            methods: {  
                 xgplayer()   
                 {  
                     let styles = {  
                        top: '0px',  
                        bottom: '540px',  
                        height: '256px',      
                        width: '100%',      
                        zindex:0,  
                        position: 'static',  
                        titleNView: {  
                            autoBackButton: true,  
                            backgroundColor: '#202028',  
                            titleColor: '#ffffff'  
                        } ,  
                        "statusbar": {    
                            "immersed": true ,//開啟沉浸式狀态欄    
                            "background": '#202028'  
                        },  
    
                        "hardwareAccelerated" : true, //開啟硬體加速  
                        "allowsInlineMediaPlayback": true,//ios關閉原生控件  
    
                     };  
                     const url = `/hybrid/html/xgplayer.html?src=${this.src}`
                     // uni.$xgplayer = plus.webview.create('','xgplayer', styles, {}); //挂載到uni全局  
                     uni.$xgplayer = plus.webview.create(url,'xgplayer'); //挂載到uni全局  
                     uni.$xgplayer.setStyle({  
                        'videoFullscreen':'landscape-primary',//視訊全屏時支援橫屏 IOS 端無效  
                     });  
    
                     // uni.$xgplayer.loadURL("/hybrid/html/xgplayer.html?src="+this.src)
    
                     uni.$xgplayer.show();  
                 }  
    
            },  
        }  
</script>

<style>
</style>      

這樣在 app 下就可以使用 xgplayer 播放視訊了。

但是…… webview 是全屏的,如果你是在單獨一個頁面進行展示完全沒有問題。

我的需求是在一個頁面中嵌入視訊播放,這就導緻 webview 樣式問題無法滿足需求。

二、renderjs

上面一種方法行不通,那就使用新的方法——renderjs

renderjs 是一個運作在視圖層的js。它比WXS更強大。它隻支援app-vue和h5。(官方文檔)

renderjs 的主要作用:

  a、大幅降低邏輯層和視圖層的通訊損耗,提供高性能的視圖互動能力

  b、在視圖層操作dom,運作for web的js庫

正好第二個作用是我的需求。最終結果也實作了。

基本使用是:

  1、建立一個 script 片段,設定 lang 為 renderjs,module 根據自己需求設定

  2、在視圖層使用可以直接調用 renderjs 的操作

要注意的點:

  a、H5下,renderjs 可以通路邏輯層的資料,app 下不能通路

  b、邏輯層不能顯示調用 renderjs 裡面的函數,需要通過視圖層間接調用,renderjs 可以通過 ownerInstance 調用 邏輯層函數

基于以上的點,具體代碼實作如下:

<template>
   // 視圖層,通過監聽綁定的值改變,調用 renderjs 的函數進行通信
    <view class="media-box" :start="startPlayValue" :change:start="xgplayer.startPlay" >
        <view id="detail-video" :detail="detail" :change:detail="xgplayer.initJs"></view>
    </view>
</template>

<script>
    export default {
        data() {
            return {
                detail:{},
                startPlayValue:1
            }
        },
        onShow() {
            this.getDetail()
        },
        methods: {
            getDetail(){
                // 改變 detail,觸發 xgPlayer.initJs(觸發startPlay同理,改變 startPlayValue即可)
            },
            onPlay(){
                console.log('開始播放')
            }
        }
    }
</script> 
<script module="xgplayer" lang="renderjs">
    let xgPlayer
    export default{
        mounted(){
        },
        methods:{
            initJs(newDetail,old,ownerInstance,instance){
                if(newDetail && newDetail.type === 1){
                    if (typeof window.Player === 'function') {
                        this.initPlayer(newDetail,ownerInstance)
                    } else {
                        // 動态引入較大類庫避免影響頁面展示
                        const script = document.createElement('script')
                        // view 層的頁面運作在根目錄
                        script.src = 'static/js/xgplayer.js'
                        script.onload = this.initPlayer.bind(this,newDetail,ownerInstance)
                        document.head.appendChild(script)
                    }
                }
            },
            
            initPlayer(detail,ownerInstance){
                xgPlayer = new Player({
                  id: 'detail-video',
                  url: detail.avUrl,
                  poster: detail.postUrl,
                  fluid: true,    // 自适應父級容器
                  playbackRate: [0.5, 0.75, 1, 1.5, 2, 2.5, 3] //傳入倍速可選數組
                });
                
                                 // 第一次播放,調用邏輯層 onPlay
                xgPlayer.once('play',()=>{
                    xgPlayer.pause()
                    console.log('首次播放')
                    ownerInstance.callMethod('onPlay')
                })
            },

            // 邏輯層通過改變 startPlayValue 來觸發 renderjs 函數
            startPlay(){
                xgPlayer.play()
            }
        }
    }
</script>