更新记录

1.1.0(2023-05-22)

本次主要更新: 1.增加 画中画恢复 回调

1.0.0(2022-11-21)

新版首发


平台兼容性

Android iOS
× 适用版本区间:11 - 16

原生插件通用使用流程:

  1. 购买插件,选择该插件绑定的项目。
  2. 在HBuilderX里找到项目,在manifest的app原生插件配置中勾选模块,如需要填写参数则参考插件作者的文档添加。
  3. 根据插件作者的提供的文档开发代码,在代码中引用插件,调用插件功能。
  4. 打包自定义基座,选择插件,得到自定义基座,然后运行时选择自定义基座,进行log输出测试。
  5. 开发完毕后正式云打包

付费原生插件目前不支持离线打包。
Android 离线打包原生插件另见文档 https://nativesupport.dcloud.net.cn/NativePlugin/offline_package/android
iOS 离线打包原生插件另见文档 https://nativesupport.dcloud.net.cn/NativePlugin/offline_package/ios

注意事项:使用HBuilderX2.7.14以下版本,如果同一插件且同一appid下购买并绑定了多个包名,提交云打包界面提示包名绑定不一致时,需要在HBuilderX项目中manifest.json->“App原生插件配置”->”云端插件“列表中删除该插件重新选择


KJ-Player

原生系统自带播放器、支持第三方播放器无缝添加画中画(全局)、可完全自定义界面、支持格式MP4、m3u8、mov、3gp、mpv等等、 全屏、快进、速率

andorid版本

画中画(全局)、里面的播放器为官方的video、支持为第三方播放器无缝添加(进度同步更新)、完全关闭app/清后台都不会消失: https://ext.dcloud.net.cn/plugin?id=10185

注意事项

1.画中画需要配置:"UIBackgroundModes" : "audio",manifest.json->App常用其它设置->后台运行能力

2.全屏需要配置:manifest.json->app-plus 下添加"screenOrientation" : [ "portrait-primary", "landscape-primary" ]

第三方播放器无缝添加画中画(全局) subNVue

<template>
    <view class="content">
        <KJ-Player class="player" ref="player" :style="{width:'100%',height:palyerHeight}"
            @onTimeChanged="onTimeChanged" @onKVO="onKVO" @onNotification="onNotification" @onPip="onPip"
            @onSystem="onSystem">
        </KJ-Player>
    </view>
</template>

<script>
    export default {
        data() {
            return {
                url: "http://baobab.kaiyanapp.com/api/v1/playUrl?vid=164016&resourceType=video&editionType=high&source=aliyun&playUrlType=url_oss",
                duration: 60 * 60 * 1000, //精确总时长
                current: 0, //video进度
                pip_currentTime: 0,
                isSet: false,
                isPaly: false,
                path: null
            }
        },
        onLoad() {
            uni.$on('to-pip-path', (res) => {
                this.path = res.path;
            });
            uni.$on('to-pip', (res) => {
                console.log(JSON.stringify(res));
                uni.showLoading({
                    title: "开启画中画..."
                })
                this.isSet = false;
                this.pip_currentTime = res.currentTime;
                this.url = res.url;
                this.path = res.path;
                this.init2();
            })
        },
        methods: {
            onTimeChanged(res) {
                this.duration = parseInt(res.detail.total);
                this.current = parseInt(res.detail.current);
                if (this.current > this.pip_currentTime && this.isSet == false) {
                    this.isSet = true;
                    this.$refs.player.startPictureInPicture()
                    this.$refs.player.setMuted({
                        "is": false
                    }, (res) => {
                        console.log("setMuted:" + JSON.stringify(res))
                    })
                }
            },
            onKVO(res) {
                console.log("onKVO:" + JSON.stringify(res.detail))
                var attribute = res.detail.attribute
                var value = res.detail.value
                if (attribute == "timeControlStatus") {
                    if (value == 0) { //暂停
                    } else if (value == 1) { //由于媒体缓冲数据不足而导致播放停止
                    } else if (value == 2) { //播放
                        if (this.isSet == false) {
                            this.$refs.player.setMuted({
                                "is": true
                            }, (res) => {
                                console.log("setMuted:" + JSON.stringify(res))
                            })
                            var dic = {
                                "second": this.pip_currentTime
                            }
                            this.$refs.player.seekToTime(dic, (res) => {
                                console.log("seekToTime:" + JSON.stringify(res))
                            })
                        }
                    }
                } else if (attribute == "playerItemStatus") {
                    if (value == 0) { //未知
                    } else if (value == 1) { //已准备好播放
                    } else if (value == 2) { //失败
                        uni.hideLoading();
                        uni.showModal({
                            content: "画中画开启失败"
                        })
                    }
                } else if (attribute == "status") {
                    if (value == 0) { //未知
                    } else if (value == 1) { //已准备好播放
                    } else if (value == 2) { //失败
                        uni.hideLoading();
                        uni.showModal({
                            content: "画中画开启失败"
                        })
                    }
                }
            },
            onNotification(res) {
                console.log("onNotification:" + JSON.stringify(res.detail))
                if (res.detail.method == "AVPlayerItemTimeJumpedNotification") {
                    console.log("发生变化");
                } else if (res.detail.method == "AVPlayerItemDidPlayToEndTimeNotification") {
                    console.log("播放结束");
                } else if (res.detail.method == "AVPlayerItemFailedToPlayToEndTimeNotification") {
                    console.log("未能播放到其结束时间就中断");
                } else if (res.detail.method == "AVPlayerItemPlaybackStalledNotification") {
                    console.log("播放暂停");
                }
            },
            onPip(res) {
                console.log("onPip:" + JSON.stringify(res.detail))
                if (res.detail.method == "WillStartPictureInPicture") {
                    console.log("即将开启画中画");
                    uni.hideLoading();
                } else if (res.detail.method == "DidStartPictureInPicture") {
                    console.log("已开启画中画");
                } else if (res.detail.method == "failedToStartPictureInPicture") {
                    console.log("开启画中画失败");
                    uni.hideLoading();
                    uni.showModal({
                        content: "画中画开启失败"
                    })
                } else if (res.detail.method == "WillStopPictureInPicture") {
                    this.$refs.player.getCurrentTime((res) => {
                        console.log("getCurrentTime:" + JSON.stringify(res))
                        uni.$emit('pip-to', {
                            currentTime: res.result,
                            url: this.url
                        });
                        if (this.path != null) {
                            uni.navigateTo({
                                url: this.path + "?pip_currentTime=" + res.result
                            })
                        }
                    })
                    console.log("即将停止画中画");
                } else if (res.detail.method == "DidStopPictureInPicture") {
                    console.log("已停止画中画");
                } else if (res.detail.method == "restoreUserInterfaceForPictureInPictureStop") {
                    console.log("画中画恢复");
                }
            },
            onSystem(res) { //系统界面,才支持
                console.log("onSystem:" + JSON.stringify(res.detail))
                if (res.detail.method == "willBeginFullScreen") {
                    console.log("即将开始全屏");
                } else if (res.detail.method == "willEndFullScreen") {
                    console.log("即将退出全屏");
                }
            },
            comminit(playerType) {
                var dic = {
                    "playerType": playerType, //custom system
                    "urlType": "network", //local(本地路径-传绝对路径plus.io.convertLocalFileSystemURL) network(网络地址)
                    "url": this.url,
                    "autoPlay": true,
                    "allowsPictureInPicturePlayback": true, //是否开启画中画
                    "canStartPictureInPictureAutomaticallyFromInline": true, //ios14.2 是否 进入后台,自动启动画中画
                    "videoGravity": "ResizeAspect", //设置视频拉伸模式
                    "systemPlayer": { //playerType为system有效
                        // "showsPlaybackControls": true, //是否显示媒体播放组件
                        // "showsTimecodes": true, //ios13 
                        // "allowsVideoFrameAnalysis": true, 
                        // "updatesNowPlayingInfoCenter": true,
                        // "entersFullScreenWhenPlaybackBegins": true,
                        // "exitsFullScreenWhenPlaybackEnds": true,
                        // "requiresLinearPlayback": true,
                    },
                };
                this.$refs.player.init(dic, (res) => {
                    console.log("init:" + JSON.stringify(res))
                })
            },
            init2() {
                this.comminit("custom")
            }
        }
    }
</script>

<style>
    .play {
        justify-content: center;
        align-items: center;
        background-color: black;
    }
</style>

官方video添加画中画(全局)

<template>
    <div>
        <video id='video1' class="video" :src="src" autoplay="true" duration="" :danmu-list="list" danmu-btn="true"
            enable-danmu="true" :loop="true" initial-time="" direction="-90" show-mute-btn="true" @play="onstart"
            @pause="onpause" @ended="onfinish" @error="onfail" @waiting="waiting" @timeupdate="timeupdate"
            @fullscreenchange="fullscreenchange"></video>
        <button class="btn" @click="pip">画中画(全局)</button>
        <button class="btn" @click="play">播放</button>
        <button class="btn" @click="pause">暂停</button>
        <button class="btn" @click="seek">跳转到指定位置</button>
        <button class="btn" @click="stop">停止</button>
        <button class="btn" @click="fullScreen">全屏</button>
        <button class="btn" @click="exitFullScreen">退出全屏</button>
        <button class="btn" @click="playbackRate">设置倍速</button>
        <button class="btn" @click="sendDanmu">发送弹幕</button>
    </div>
</template>

<script>
    export default {
        data() {
            return {
                src: "https://img.cdn.aliyun.dcloud.net.cn/guide/uniapp/%E7%AC%AC1%E8%AE%B2%EF%BC%88uni-app%E4%BA%A7%E5%93%81%E4%BB%8B%E7%BB%8D%EF%BC%89-%20DCloud%E5%AE%98%E6%96%B9%E8%A7%86%E9%A2%91%E6%95%99%E7%A8%8B@20181126-lite.m4v",
                fil: true,
                list: [{
                    text: '要显示的文本',
                    color: '#FF0000',
                    time: 9
                }],
                currentTime: 0,
                pip_currentTime: null,
                isPip: false
            }
        },
        onLoad(options) {
            this.pip_currentTime = options.pip_currentTime;

            uni.$on('pip-to', (res) => {
                console.log(JSON.stringify(res));
                this.context.seek(res.currentTime);
                this.play();
            })
        },
        onReady() {
            console.log("pip_currentTime:" + this.pip_currentTime);
            this.context = uni.createVideoContext("video1", this);
            if (this.pip_currentTime != undefined) {
                setTimeout((res) => {
                    this.context.seek(this.pip_currentTime);
                }, 100)
            }
        },
        onUnload() {
            if (this.isPip) {
                uni.$emit('to-pip-path', {
                    path: "/pages/index/video",
                });
            }
        },
        onBackPress() {
            console.log("onBackPress")
        },
        methods: {
            pip() {
                this.isPip = true;
                this.pause();
                uni.$emit('to-pip', {
                    currentTime: this.currentTime,
                    url: this.src,
                    path: null,
                });
            },
            onstart(e) {
                console.log("onstart:" + JSON.stringify(e));
            },
            onpause(e) {
                console.log("onpause:" + JSON.stringify(e));
            },
            onfinish(e) {
                console.log("onfinish:" + JSON.stringify(e));
            },
            onfail(e) {
                console.log("onfail:" + JSON.stringify(e));
            },
            fullscreenchange(e) {
                console.log("fullscreenchange:" + JSON.stringify(e));
            },
            waiting(e) {
                console.log("waiting:" + JSON.stringify(e));
            },
            timeupdate(e) {
                //console.log("timeupdate:" + JSON.stringify(e));
                this.currentTime = e.detail.currentTime
            },
            play() {
                this.context.play();
            },
            pause() {
                this.context.pause();
            },
            seek() {
                this.context.seek(20);
            },
            stop() {
                this.context.stop();
            },
            fullScreen() {
                this.context.requestFullScreen({
                    direction: 90
                });
            },
            exitFullScreen() {
                this.context.exitFullScreen();
            },
            sendDanmu() {
                this.context.sendDanmu({
                    text: '要显示的弹幕文本',
                    color: '#FF0000'
                });
            },
            playbackRate() {
                this.context.playbackRate(2);
            }
        }
    }
</script>

<style>
    .video {
        width: 750rpx;
        /* #ifdef H5 */
        width: 100%;
        /* #endif */
        height: 400rpx;
        background-color: #808080;
    }

    .btn {
        margin-top: 5px;
        margin-bottom: 5px;
    }
</style>

原生系统自带播放器使用

<template>
    <view class="content">
        <KJ-Player class="player" ref="player" :style="{width:'100%',height:palyerHeight}"
            @onTimeChanged="onTimeChanged" @onKVO="onKVO" @onNotification="onNotification" @onPip="onPip"
            @onSystem="onSystem">
            <cover-view v-if="isShowVideoview" class="video-view" :style="{width:'100%',height:palyerHeight}"
                @click="tap" @touchstart="touchStartHandle" @touchend="touchEndHandle" @touchcancel="touchCancelHandle"
                @touchmove="touchMoveHandle">
                <text class="tip" v-if="isShowTip"
                    :style="{position:'absolute',left:0,right:0,top:tipTop}">{{tip}}</text>
                <view class=" top-title" :style="{width:'100%'}" v-if="isShowTitle">
                    <view>
                        <button type="primary" @click="pip2">画中画(全局)</button>
                    </view>
                    <text :style="{color:'#fff'}">标题</text>
                    <view>
                        <button type="primary" @click="pip">画中画</button>
                    </view>
                </view>
                <view class="bottom-title" :style="{width:'100%'}" v-if="isShowTitle">
                    <button type="primary" @click="playOrPause">{{playOrPauseText}}</button>
                    <text class="text">{{leftTime}}</text>
                    <view class="fullControls-center">
                        <chunLei-slider :max="duration" :value="current" :style="{width:`${fullControlsWidth-40}px`}"
                            :screenLeft="40" :width="fullControlsWidth-40" @change="changeCurrent" :ratio="1">
                        </chunLei-slider>
                    </view>
                    <text class="text">{{rightTime}}</text>
                    <button type="primary" @click="full">全屏</button>
                </view>
            </cover-view>
        </KJ-Player>
        <view class="btns">
            <button type="primary" @click="init">初始化(系统自带界面)</button>
            <button type="primary" @click="init2">初始化(自定义界面)</button>
            <button type="primary" @click="stop">销毁</button>
            <button type="primary" @click="replaceCurrentItemWithPlayerItem">切换播放源</button>
            <button type="primary" @click="getCurrentTime">获取当前时间</button>
            <button type="primary" @click="getDuration">获取时长</button>
            <button type="primary" @click="play">播放</button>
            <button type="primary" @click="pause">暂停</button>
            <button type="primary" @click="getStatus">获取状态</button>
            <button type="primary" @click="getTimeControlStatus">获取时间控制状态</button>
            <button type="primary" @click="setMuted">设置是否静音</button>
            <button type="primary" @click="getMuted">获取是否静音</button>
            <button type="primary" @click="setVolume">设置音量</button>
            <button type="primary" @click="getVolume">获取音量</button>
            <button type="primary" @click="setRate">设置速率</button>
            <button type="primary" @click="getRate">获取速率</button>
            <button type="primary" @click="seekToTime">设置进度</button>
            <button type="primary" @click="setVideoGravity">设置视频拉伸模式</button>
            <button type="primary" @click="isPictureInPictureSuspended">设备是否支持画中画</button>
            <button type="primary" @click="pip">自动切换画中画</button>
            <button type="primary" @click="isPictureInPictureActive">是否已开启画中画</button>
            <button type="primary" @click="startPictureInPicture">开启画中画</button>
            <button type="primary" @click="stopPictureInPicture">停止画中画</button>
        </view>
    </view>
</template>

<script>
    import chunLeiSlider from '@/components/chunLei-slider/chunLei-slider.nvue'

    export default {
        components: {
            chunLeiSlider
        },
        data() {
            return {
                url: "http://baobab.kaiyanapp.com/api/v1/playUrl?vid=164016&resourceType=video&editionType=high&source=aliyun&playUrlType=url_oss",
                isShowVideoview: false,
                duration: 60 * 60 * 1000, //精确总时长
                fullControlsWidth: '200', //全屏宽
                current: 0, //video进度
                leftTime: "00:00:00",
                rightTime: "00:00:00",
                statusBarHeight: "20px",
                getStatusBarHeight: "20px",
                headerHeight: "44px",
                palyerHeight: "500rpx",
                tipTop: "250rpx",
                tip: "加载中...",
                isShowTip: true,
                isShowTitle: true,
                hideTitleTime: 6000,
                isFull: false,
                playOrPauseText: "播放",
                touchHandleType: false, //滑动记录 progress // light // voice
                handleDynamicX: 0, // 动态记录滑动的记录X轴
                handleDynamicY: 0, // 动态记录Y轴滑动距离
                videoNowLight: 0, // 当前屏幕的亮度
                videoNowVoice: 0, // 当前的音量
                onceClickTimer: null,
                changing: false,
                isPip: true,
                pip_currentTime: null,

            }
        },
        onLoad(options) {
            uni.$emit('to-pip-path', {
                path: null,
            });
            this.pip_currentTime = options.pip_currentTime;
            uni.$on('pip-to', (res) => {
                console.log(JSON.stringify(res));
                var dic = {
                    "second": res.currentTime + ""
                }
                this.$refs.player.seekToTime(dic, (res) => {
                    console.log("seekToTime:" + JSON.stringify(res))
                    this.play();
                })
            })
        },
        onReady() {
            this.init2();
            setTimeout((res) => {
                this.$refs.player.sendSubviewToBack()
                if (this.pip_currentTime != undefined) {
                    var dic = {
                        "second": this.pip_currentTime + ""
                    }
                    this.$refs.player.seekToTime(dic, (res) => {
                        console.log("seekToTime:" + JSON.stringify(res))
                        this.play();
                    })
                }
            }, 100)
        },
        onUnload() {
            if (this.isPip) {
                uni.$emit('to-pip-path', {
                    path: "/pages/index/index",
                });
            }
        },
        onBackPress() {

        },
        (res) {
            console.log(JSON.stringify(res))
            if (res.deviceOrientation == "portrait") {
                this.isFull = false;
                plus.navigator.showSystemNavigation();
                this.palyerHeight = '500rpx';
                this.tipTop = '250rpx';
                this.fullControlsWidth = uni.getSystemInfoSync().screenWidth - 200;
                this.exitFullScreen()

            } else if (res.deviceOrientation == "landscape") {
                this.isFull = true;
                plus.navigator.hideSystemNavigation();
                this.palyerHeight = '750rpx'
                this.tipTop = '375rpx';
                this.fullControlsWidth = uni.getSystemInfoSync().screenWidth - 200;
                this.requestFullScreen()
            }
        },
        methods: {
            pip2() {
                this.isPip = true;
                this.pause();
                this.$refs.player.getCurrentTime((res) => {
                    console.log("getCurrentTime:" + JSON.stringify(res))
                    uni.$emit('to-pip', {
                        currentTime: res.result + "",
                        url: this.url,
                        path: null
                    });
                })
            },
            onTimeChanged(res) {
                this.duration = parseInt(res.detail.total);
                this.current = parseInt(res.detail.current);
                this.leftTime = this.formatDuring(this.current)
                this.rightTime = this.formatDuring(this.duration)
            },
            onKVO(res) {
                console.log("onKVO:" + JSON.stringify(res.detail))
                var attribute = res.detail.attribute
                var value = res.detail.value
                if (attribute == "timeControlStatus") {
                    if (value == 0) { //暂停
                        this.playOrPauseText = "播放";
                    } else if (value == 1) { //由于媒体缓冲数据不足而导致播放停止
                        this.playOrPauseText = "暂停";
                    } else if (value == 2) { //播放
                        this.tip = "加载中...";
                        this.isShowTip = false;
                        this.playOrPauseText = "暂停";
                    }
                } else if (attribute == "playerItemStatus") {
                    if (value == 0) { //未知
                        this.playOrPauseText = "播放";
                    } else if (value == 1) { //已准备好播放
                        this.playOrPauseText = "暂停";
                    } else if (value == 2) { //失败
                        this.tip = "播放失败";
                        this.isShowTip = true;
                        this.playOrPauseText = "播放";
                    }
                } else if (attribute == "status") {
                    if (value == 0) { //未知
                    } else if (value == 1) { //已准备好播放
                    } else if (value == 2) { //失败
                        this.tip = "播放失败";
                        this.isShowTip = true;
                        this.playOrPauseText = "播放";
                    }
                }
            },
            onNotification(res) {
                console.log("onNotification:" + JSON.stringify(res.detail))
                if (res.detail.method == "AVPlayerItemTimeJumpedNotification") {
                    console.log("发生变化");
                } else if (res.detail.method == "AVPlayerItemDidPlayToEndTimeNotification") {
                    console.log("播放完成");
                } else if (res.detail.method == "AVPlayerItemFailedToPlayToEndTimeNotification") {
                    console.log("未能播放到其结束时间就中断");
                } else if (res.detail.method == "AVPlayerItemPlaybackStalledNotification") {
                    console.log("播放暂停");
                }
            },
            onPip(res) {
                console.log("onPip:" + JSON.stringify(res.detail))
                if (res.detail.method == "WillStartPictureInPicture") {
                    console.log("即将开启画中画");
                } else if (res.detail.method == "DidStartPictureInPicture") {
                    console.log("已开启画中画");
                } else if (res.detail.method == "failedToStartPictureInPicture") {
                    console.log("开启画中画失败");
                } else if (res.detail.method == "WillStopPictureInPicture") {
                    console.log("即将停止画中画");
                } else if (res.detail.method == "DidStopPictureInPicture") {
                    console.log("已停止画中画");
                } else if (res.detail.method == "restoreUserInterfaceForPictureInPictureStop") {
                    console.log("画中画恢复");
                }
            },
            onSystem(res) { //系统界面,才支持
                console.log("onSystem:" + JSON.stringify(res.detail))
                if (res.detail.method == "willBeginFullScreen") {
                    console.log("即将开始全屏");
                } else if (res.detail.method == "willEndFullScreen") {
                    console.log("即将退出全屏");
                }
            },
            comminit(playerType) {
                var dic = {
                    "playerType": playerType, //custom system
                    "urlType": "network", //local(本地路径-传绝对路径plus.io.convertLocalFileSystemURL) network(网络地址)
                    "url": this.url,
                    "autoPlay": true,
                    "allowsPictureInPicturePlayback": true, //是否开启画中画
                    "canStartPictureInPictureAutomaticallyFromInline": true, //ios14.2 是否 进入后台,自动启动画中画
                    "videoGravity": "ResizeAspect", //设置视频拉伸模式
                    "systemPlayer": { //playerType为system有效
                        // "showsPlaybackControls": true, //是否显示媒体播放组件
                        // "showsTimecodes": true, //ios13 
                        // "allowsVideoFrameAnalysis": true, 
                        // "updatesNowPlayingInfoCenter": true,
                        // "entersFullScreenWhenPlaybackBegins": true,
                        // "exitsFullScreenWhenPlaybackEnds": true,
                        // "requiresLinearPlayback": true,
                    },
                };
                this.$refs.player.init(dic, (res) => {
                    console.log("init:" + JSON.stringify(res))
                })
            },
            init() {
                this.isShowVideoview = false;
                this.$nextTick((res) => {
                    this.comminit("system")
                })
            },
            init2() {
                this.isShowVideoview = true;
                this.$nextTick((res) => {
                    this.comminit("custom")
                    this.duration = 60 * 60 * 1000;
                    this.current = 0;
                    this.leftTime = this.formatDuring(this.current)
                    this.rightTime = this.formatDuring(this.duration)
                })
            },
            stop() {
                this.$refs.player.stop()
            },
            replaceCurrentItemWithPlayerItem() {
                var dic = {
                    "urlType": "network", //local(本地路径-传绝对路径plus.io.convertLocalFileSystemURL) network(网络地址)
                    "url": this.url
                }
                this.$refs.player.replaceCurrentItemWithPlayerItem(dic, (res) => {
                    console.log("replaceCurrentItemWithPlayerItem:" + JSON.stringify(res))
                })
            },
            getCurrentTime() {
                this.$refs.player.getCurrentTime((res) => {
                    console.log("getCurrentTime:" + JSON.stringify(res))
                })
            },
            getDuration() {
                this.$refs.player.getDuration((res) => {
                    console.log("getDuration:" + JSON.stringify(res))
                })
            },
            play() {
                this.$refs.player.play((res) => {
                    console.log("play:" + JSON.stringify(res))
                })
            },
            pause() {
                this.$refs.player.pause((res) => {
                    console.log("pause:" + JSON.stringify(res))
                })
            },
            getStatus() {
                this.$refs.player.getStatus((res) => {
                    console.log("getStatus:" + JSON.stringify(res))
                })
            },
            getTimeControlStatus() {
                this.$refs.player.getTimeControlStatus((res) => {
                    console.log("getTimeControlStatus:" + JSON.stringify(res))
                })
            },
            setMuted() {
                var dic = {
                    "is": true
                }
                this.$refs.player.setMuted(dic, (res) => {
                    console.log("setMuted:" + JSON.stringify(res))
                })
            },
            getMuted() {
                this.$refs.player.getMuted((res) => {
                    console.log("getMuted:" + JSON.stringify(res))
                })
            },
            setVolume() {
                var dic = {
                    "volume": "1.0"
                }
                this.$refs.player.setVolume(dic, (res) => {
                    console.log("setVolume:" + JSON.stringify(res))
                })
            },
            getVolume() {
                this.$refs.player.getVolume((res) => {
                    console.log("getVolume:" + JSON.stringify(res))
                })
            },
            setRate() {
                var dic = {
                    "rate": "2.0"
                }
                this.$refs.player.setRate(dic, (res) => {
                    console.log("setRate:" + JSON.stringify(res))
                })
            },
            getRate() {
                this.$refs.player.getRate((res) => {
                    console.log("getRate:" + JSON.stringify(res))
                })
            },
            seekToTime() {
                var dic = {
                    "second": "3000.0"
                }
                this.$refs.player.seekToTime(dic, (res) => {
                    console.log("seekToTime:" + JSON.stringify(res))
                })
            },
            isPictureInPictureSuspended() {
                this.$refs.player.isPictureInPictureSuspended((res) => {
                    console.log("isPictureInPictureSuspended:" + JSON.stringify(res))
                })
            },
            pip() {
                this.$refs.player.pip()
            },

            isPictureInPictureActive() {
                this.$refs.player.isPictureInPictureActive((res) => {
                    console.log("isPictureInPictureActive:" + JSON.stringify(res))
                })
            },
            startPictureInPicture() {
                this.$refs.player.startPictureInPicture()
            },
            stopPictureInPicture() {
                this.$refs.player.stopPictureInPicture()
            },
            setVideoGravity() {
                var dic = {
                    "videoGravity": "ResizeAspectFill"
                }
                this.$refs.player.setVideoGravity(dic, (res) => {
                    console.log("setVideoGravity:" + JSON.stringify(res))
                })
            },
            requestFullScreen() {
                this.$refs.player.requestFullScreen((res) => {
                    console.log("requestFullScreen:" + JSON.stringify(res))
                })
            },
            exitFullScreen() {
                this.$refs.player.exitFullScreen((res) => {
                    console.log("exitFullScreen:" + JSON.stringify(res))
                })
            },
            playOrPause() {
                this.$refs.player.getTimeControlStatus((res) => {
                    console.log(JSON.stringify(res))
                    if (res.result == 0) { //暂停
                        this.play();
                    } else if (res.result == 1) { //由于媒体缓冲数据不足而导致播放停止
                        this.pause();
                    } else if (res.result == 2) { //播放
                        this.pause();
                    }
                })
            },
            full() {
                if (!this.isFull) {
                    plus.screen.lockOrientation("landscape-primary");
                    //this.$refs.vlc.requestFullScreen()
                } else {
                    plus.screen.lockOrientation("portrait-primary");
                    //this.$refs.vlc.exitFullScreen()
                }
                this.isFull = !this.isFull;
            },
            formatDuring(s) {
                //console.log(mss)
                var hours = parseInt(s / 60 / 60);
                if (hours < 10) {
                    hours = "0" + hours
                }
                var minutes = parseInt(s / 60 % 60);
                if (minutes < 10) {
                    minutes = "0" + minutes
                }
                var seconds = parseInt(s % 60);
                if (seconds < 10) {
                    seconds = "0" + seconds
                }
                return hours + ":" + minutes + ":" + seconds;
            },
            //拖动滑块
            changeCurrent(e) {
                this.current = e.detail.value
                console.log(JSON.stringify(e));
                this.changing = true;
                var dic = {
                    "second": "" + parseInt(this.current)
                }
                this.$refs.player.seekToTime(dic, (res) => {
                    console.log("seekToTime:" + JSON.stringify(res))
                })
            },
            changing(e) {
                this.changing = false;
            },
            full() {
                if (!this.isFull) {
                    plus.screen.lockOrientation("landscape-primary");
                    //this.$refs.vlc.requestFullScreen()
                } else {
                    plus.screen.lockOrientation("portrait-primary");
                    //this.$refs.vlc.exitFullScreen()
                }
                this.isFull = !this.isFull;
            },
            tap() {
                console.log("tap")
                if (this.onceClickTimer != null) {
                    clearTimeout(this.onceClickTimer);
                    this.onceClickTimer = null;
                }
                this.isShowTitle = !this.isShowTitle;
                this.$forceUpdate()
                if (this.isShowTitle) {
                    this.onceClickTimer = setTimeout(() => {
                        clearTimeout(this.onceClickTimer);
                        this.onceClickTimer = null;
                        this.isShowTitle = false;
                    }, this.hideTitleTime)
                }
            },
            //监听当前操作
            touchStartHandle(e) {
                console.log(e);
                this.touchStartTimeStamp = new Date().getTime();
                this.handleDynamicY = e.changedTouches[0].screenY;
                this.handleDynamicX = e.changedTouches[0].screenX;
            },
            //监听抬起操作
            touchEndHandle(e) {
                //this.tap();
                if (this.touchHandleType) {
                    this.touchStartTimeStamp = 0;
                    this.handleDynamicY = 0;
                    this.handleDynamicX = 0;
                    this.touchHandleType = false;
                    if (this.progressBtnStatus) {
                        this.progressBtnStatus = false;
                        this.progressPercent = this.progressBtnPercent;
                    }
                }

            },
            // 监听是否触发滑动事件
            touchMoveHandle(e) {
                // 判断左右上下滑动是否超过10px
                let X = e.changedTouches[0].screenX;
                let Y = e.changedTouches[0].screenY;
                if (this.touchHandleType) {
                    this.handleFun(X, Y);
                    return;
                }
                let chaX = Math.abs(X - this.handleDynamicX);
                let chaY = Math.abs(Y - this.handleDynamicY);
                if (chaX > 10 || chaY > 10) {
                    if (chaX > 10) {
                        this.touchHandleType = 'progress';
                        this.handleDynamicX = X;
                    } else {
                        let left = uni.getSystemInfoSync().screenWidth / 2;
                        if (this.handleDynamicX > left) {
                            this.touchHandleType = 'voice'
                        } else {
                            this.touchHandleType = 'light'
                        }
                        this.handleDynamicY = Y;
                    }
                }
            },
            // 操作当前的方法
            handleFun(X, Y) {
                let chaX = X - this.handleDynamicX;
                let chaY = Y - this.handleDynamicY;
                switch (this.touchHandleType) {
                    case 'progress':
                        console.log("progress")
                        this.progressBtnStatus = true;
                        if (chaX > 0) {
                            if (this.current >= this.duration) {
                                this.current = this.duration;
                            } else {
                                this.current += 1000;
                            }
                        } else {
                            if (this.current <= 0) {
                                this.current = 0;
                            } else {
                                this.current -= 1000;
                            }
                        }
                        var dic = {
                            "second": "" + parseInt(this.current)
                        }
                        this.$refs.player.seekToTime(dic, (res) => {
                            console.log("seekToTime:" + JSON.stringify(res))
                        })
                        break;
                    case 'light':
                        console.log("light")
                        if (chaY < 0) {
                            if (this.videoNowLight + 0.02 >= 1) {
                                this.videoNowLight = 1;
                            } else {
                                this.videoNowLight += 0.02
                            }
                        } else {
                            if (this.videoNowLight - 0.02 <= 0) {
                                this.videoNowLight = 0;
                            } else {
                                this.videoNowLight -= 0.02
                            }
                        }
                        plus.screen.setBrightness(this.videoNowLight)
                        break;
                    case 'voice':
                        console.log("voice")

                        if (chaY < 0) {
                            if (this.videoNowVoice + 0.02 >= 1) {
                                this.videoNowVoice = 1;
                            } else {
                                this.videoNowVoice += 0.02
                            }
                        } else {
                            if (this.videoNowVoice - 0.02 <= 0) {
                                this.videoNowVoice = 0;
                            } else {
                                this.videoNowVoice -= 0.02
                            }
                        }
                        plus.device.setVolume(this.videoNowVoice);

                        break;
                    default:
                        this.touchHandleType = false;
                        break;
                }
                this.handleDynamicX = X;
                this.handleDynamicY = Y;
            }
        }
    }
</script>

<style>
    .text {
        color: #fff;
        font-size: 10px;
    }

    .play {
        justify-content: center;
        align-items: center;
        background-color: black;
    }

    .video-view {
        position: absolute;
        top: 0;
        bottom: 0;
        left: 0;
        right: 0;
        z-index: 999;
    }

    .tip {
        position: absolute;
        left: 0;
        right: 0;
        top: 250rpx;
        text-align: center;
        color: #fff
    }

    .top-title,
    .bottom-title {
        position: absolute;
        left: 0;
        right: 0;
        height: 70px;
        background-color: rgba(0, 0, 0, 0.1);
        display: flex;
        justify-content: space-between;
        flex-direction: row;
        align-items: center;
        color: #fff;
        padding: 16px;
    }

    .top-title {
        top: 0;
        width: 750rpx;
    }

    .bottom-title {
        bottom: 0;
        width: 750rpx;
    }

    .fullControls-center {
        flex-direction: row;
        align-items: center;
        justify-content: center;
        height: 40px;
    }

    .btns {
        margin-top: 40px;
        display: flex;
        flex-wrap: wrap;
        flex-direction: row;
        align-items: center;
        justify-content: center;
    }
</style>

隐私、权限声明

1. 本插件需要申请的系统权限列表:

画中画需要配置:"UIBackgroundModes" : "audio", 全屏需要配置:"screenOrientation" : [ "portrait-primary", "landscape-primary" ]

2. 本插件采集的数据、发送的服务器地址、以及数据用途说明:

插件不采集任何数据

3. 本插件是否包含广告,如包含需详细说明广告表达方式、展示频率:

使用中有什么不明白的地方,就向插件作者提问吧~ 我要提问