背景:在uniapp中因原生video组件功能有限,选择引入
xgplayer
库来展示视频播放等功能。并且APP端无法操作dom
,所以使用了renderjs
。
其他的不多说,主要列举一下renderjs中需要注意的点:
1、使用:在标签后,添加<script module="xgPlayerModule" lang="renderjs"></script >
,然后有关操作dom的代码都写在script 标签里面。其中module的值是自定义
的,后续会用这个值来调用renderjs的方法。
2、普通 script 标签是逻辑层
,带renderjs的 script 标签是视图层
。
3、逻辑层向视图层传值:在 template 某元素上添加 :属性名=“vue 变量”:change:属性名=“renderjs 模块名.方法名”
(其中 vue 变量 为 Vue 组件中的某个数据, renderjs 模块名 为之前定义的 module 属性的值,当 vue 变量 值改变时会触发 renderjs模块名.方法名 的方法)。例如:
<view :iosTimes="iosTimes" :change:iosTimes="xgPlayerModule.changeTimes"></view><script module="xgPlayerModule" lang="renderjs">export default {data(){return {renderIosTimes: null}},methods: {changeTimes() { // 当检测到iosTimes变化时,触发此方法,重新赋值后,保存在renderjs里面的renderIosTimes 变量中,因为后面renderjs里面的其他方法要使用这个值。this.renderIosTimes = this.iosTimes}}}
</script>
4、**视图层向逻辑层传参:**在 template 元素的事件绑定中使用 @事件=“renderjs 模块名.方法名”
,通过该方式触发 renderjs 中的方法,然后在这个方法中可以使用 this.$ownerinstance.callmethod('vue 组件中的方法名', 参数)
来调用普通 Vue 组件中的方法并传值。
this.$ownerInstance.callMethod('playerMethods')
接下来就是在renderjs中,通过xgplayer创建视频,并且完成交互
准备:
npm install xgplayer --save
以下是完整的代码案例:
video.vue中调用xgplayer组件
<xg-player :data-idkey="modId" ref="video" :videoConfig="videoConfig" ></xg-player>import xgPlayer from '@/components/player/xgplayer';
<script>export default {data(){return {videoConfig: {videoUrl: '', // 播放地址lastPlayTime: '' // 上次播放时间} }},methods: {changeTimes() { // 当检测到iosTimes变化时,触发此方法,重新赋值后,保存在renderjs里面的renderIosTimes 变量中,因为后面renderjs里面的其他方法要使用这个值。this.renderIosTimes = this.iosTimes}},onHide: function() { // 退出应用时调用this.$refs['video'].beforeLeave() // 调用子组件的方法,暂停视频播放}}
</script>
xgplayer.vue组件中:
<template><view><!-- 视频 --><view:id='videoId'class="mse-box":style="customStyle"v-if="type === 'VOD'":conEnd="conEnd" :change:conEnd="xgPlayerModule.initVideo"></view><view :iosTimes="iosTimes" :change:iosTimes="xgPlayerModule.changeTimes"></view><view :modOpenTrial="modOpenTrial" :change:modOpenTrial="xgPlayerModule.changeModOpenTrial"></view><view :playOrPauseStatus="playOrPauseStatus" :change:playOrPauseStatus="xgPlayerModule.playOrPauseVideoRenderjs"></view></view>
</template><!-- 逻辑层 -->
<script>
export default {name: 'xgPlayerHls',data: function() {return {config: {id: this.videoId,url: '',fluid: true,playbackRate: [0.75, 1, 1.5, 2],defaultPlaybackRate: 1,definitionActive: 'click',poster: '',volume: 1,autoplay: false, // 手动点击播放,节省用户流量playsinline: true,lastPlayTime: 0, //视频起播时间(单位:秒)lastPlayTimeHideDelay: 3,enableVideoDbltouch: true,rotateFullscreen: true,// rotate: {// innerRotate: true,// clockwise: false// },fitVideoSize: 'auto'},inFullscreen: false,inLandscape: false,conEnd: null,playOrPauseStatus: 'pause'};},components: {},computed: {// h5通过监听屏幕角度去写入样式customStyle() {const that = this;if (that.inFullscreen && that.inLandscape) {return {height: '100vh !important',minWidth: '100%',width: '100% !important',left: '0%',transform: 'rotate(0deg)'};} else if (that.inLandscape) {return {width: '100% !important',height: '400rpx !important'};} else {return {width: '100%',height: '400rpx'};}}},props: {rootStyle: {type: Object,default() {return {};}},iosTimes: {type: Boolean,default() {return false;}},videoConfig: {type: Object,default() {return {videoUrl: '', lastPlayTime: 0};}},modOpenTrial: {type: Boolean,default() {return true;}},modDrag: {type: Boolean,default() {return true;}},fastForward: {type: Boolean,default() {return true;}},type: {type: String,default() {return 'VOD';}},videoId: {type: String,default() {return 'mse';}}},methods: {beforeLeave() { // 离开页面暂停视频播放this.playOrPauseStatus = 'pause'},playVideo() {this.playOrPauseStatus = 'play'},pauseVideo() {this.playOrPauseStatus = 'pause'},handleOrientation() {const orientation = window.orientation;console.log('orientation=当设备的方向发生变化时触发的事件===', orientation);switch (orientation) {case 0:// 竖屏this.inLandscape = false;break;case 90:// 左横屏this.inLandscape = true;break;case -90:// 右横屏this.inLandscape = true;break;case 180:// 倒立break;default:// 未知break;}},fullScreenMe() { // 进入全屏this.inFullscreen = true;this.$emit('on-goLandscape', 'ON');},exitFullScreenMe() { // 退出全屏this.inFullscreen = false;this.$emit('on-goLandscape', 'OFF');},playTimeUpdate(currentTime) { // timeupdate播放中// console.log('播放中=============');this.$emit('playerVideo', currentTime);},openTrialMe() {// 弹框有问题this.$dialog.alert({width: '80%',confirmButtonColor: '#00aeef',confirmButtonText: this.$t('mall_10'),message: this.$t('see_end')});},playerMethods() { // 播放console.log('播放============');this.playOrPauseStatus = 'play'this.$emit('videoPlay')},playerPauseMethods() { // 暂停console.log('暂停============');this.playOrPauseStatus = 'pause'this.$emit('videoPause')},init() {if (this.videoConfig.videoUrl) {if (this.type === 'VOD') {this.config.id = this.videoId;this.config.lastPlayTime = this.videoConfig.lastPlayTime;this.config.url = this.videoConfig.videoUrl;this.config.autoplay =this.videoConfig.autoplaythis.config.ignores = this.fastForward ? [] : ['progress'];if (this.videoConfig.duration) {this.config.duration = this.videoConfig.duration;}// m3u8 格式播放if (this.videoConfig.videoUrl.indexOf('m3u8') !== -1) {this.config.preloadTime = 15; // 预加载时间15sthis.config.minCachedTime = 5; // 最小缓存时间// iOS手机不兼容此项属性,故作此判断// 使用 uni.getSystemInfoSync() 获取系统信息const systemInfo = uni.getSystemInfoSync();const platform = systemInfo.platform;if (platform === 'android') {this.config.useHls = true;}}this.conEnd = this.config; // config赋值完成}}}},mounted() {// 是否有权限观看完整视频, true: 能 , false: 禁止拖拽; 限制 10%;this.config.disableProgress = !this.modOpenTrial;//如果禁止拖动,后台设置的false,前端设置值得是true.如果允许拖动,后台设置的true,前端设置值得是false.this.config.allowSeekPlayed = !this.modDrag;// #ifdef APP-PLUS// 监听事件 当设备的方向发生变化时触发的事件plus.globalEvent.addEventListener('orientationchange', this.handleOrientation);// #endif// #ifndef APP-PLUSwindow.addEventListener('orientationchange', this.handleOrientation);// #endifthis.init();},watch: {modOpenTrial(val) {// 是否有权限观看完整视频, true: 能 , false: 禁止拖拽; 限制 10%;this.config.disableProgress = !this.val;}}
};
</script><!-- 视图层 -->
<script module="xgPlayerModule" lang="renderjs">import xgPlayer from 'xgplayer';import HlsJsPlayer from 'xgplayer-hls.js';export default {data(){return {player: null,renderIosTimes: null,renderModOpenTrial: null}},mounted() {},beforeDestroy() {this.player && typeof this.player.destroy === 'function' && this.player.destroy();},methods: {playOrPauseVideoRenderjs() { // 控制视频播放和暂停console.log('暂停视频 或者 播放', this.playOrPauseStatus);if (this.player) {if (this.playOrPauseStatus === 'play') {this.player.play();} else {this.player.pause();}}},changeTimes() {this.renderIosTimes = this.iosTimes},changeModOpenTrial() {this.renderModOpenTrial = this.modOpenTrial},initVideo(newVal,old,ownerInstance,instance) {let that = thisif (that.conEnd && that.conEnd.id && that.conEnd.url && !that.player) {console.log('视图层的initVideo方法========');if (that.player) {that.player.destroy();}if (that.conEnd.url.indexOf('m3u8') !== -1) {that.player = new HlsJsPlayer(that.conEnd);} else { // 不是m3u8that.player = new xgPlayer(that.conEnd);if (that.renderIosTimes) {if (that.player) {that.player.start(that.conEnd.url);that.player.play();}}}console.log('that.player=======', that.player);// 播放that.player.on('play', function () {// 调用逻辑层方法that.$ownerInstance.callMethod('playerMethods')})// 暂停that.player.on('pause', function () {// 调用逻辑层方法that.$ownerInstance.callMethod('playerPauseMethods')})// 播放中that.player.on('timeupdate', function(resPlayer) {// 是否有权限观看完整视频, true: 能 , false: 禁止拖拽; 限制 10%;if (!that.renderModOpenTrial && (resPlayer.currentTime / resPlayer.duration) >= 0.1) {resPlayer.pause();// resPlayer.currentTime = 0;that.$ownerInstance.callMethod('openTrialMe')}// 调用逻辑层方法that.$ownerInstance.callMethod('playTimeUpdate', resPlayer.currentTime)});// 进入全屏that.player.on('getRotateFullscreen', function(value) {if (document.getElementsByClassName('water-turn')[0]) {document.getElementsByClassName('water-turn')[0].style.transform = 'rotate(90deg)';}that.$ownerInstance.callMethod('fullScreenMe')});// 退出全屏that.player.on('exitRotateFullscreen', function(value) {if (document.getElementsByClassName('water-turn')[0]) {document.getElementsByClassName('water-turn')[0].style.transform = 'rotate(0deg)';}that.$ownerInstance.callMethod('exitFullScreenMe')});}}}}
</script>