视频播放组件

This commit is contained in:
daihh
2022-11-18 16:21:16 +08:00
parent 9ea597a715
commit 0cac363df4
3 changed files with 131 additions and 130 deletions

View File

@@ -1,29 +1,29 @@
<template> <template>
<view class="video-box" @click="clickVideo"> <view id="xvideoPlayer-box" class="video-box">
<video id="myVideo" style="width: 100%;" <video id="xvideoPlayer" style="width: 100%;"
:src="url" :src="url"
:controls="false" :controls="false"
:enable-play-gesture="true" :enable-play-gesture="false"
:initial-time="initPlayingTime" :initial-time="initPlayingTime"
@error="onError" @error="onError"
@touchend="onTouchend" @touchend="onTouchend"
@play="onPlay" @play="onPlay"
@pause="onPause" @pause="onPause"
@ended="onEnded" @ended="onEnded"
@timeupdate="onPlaying" @timeupdate="onTimeUpdate"
@fullscreenchange="onFullScreen" @fullscreenchange="onFullScreen"
@loadeddata="onLoad" @loadeddata="onLoad"
@loadedmetadata="onMetaLoad" @loadedmetadata="onMetaLoad"
@controlstoggle="onControlsToggle" @controlstoggle="onControlsToggle"
></video> ></video>
<view v-if="contrlShow"> <view id="xplayer-control" >
<view class="process-container"> <view class="process-container" v-if="contrlShow">
<view class="controller-play"> <view class="controller-play">
<image :src="require(playing? './images/pause.png':'./images/play.png')" @click='videoOpreation'/> <image :src="require(playing? './images/pause.png':'./images/play.png')" @click.stop='videoOpreation'/>
</view> </view>
<view class="currtime">{{currtime}}</view> <view class="currtime">{{currtime}}</view>
<view class='slider-container'> <view class='slider-container'>
<slider :disabled="!drag" @change="sliderChange" @changing="sliderChanging" step="1" :value="sliderValue" backgroundColor="#9f9587" activeColor="#d6d2cc" block-color="#FFFFFF" block-size="12"/> <slider :disabled="!drag" @change.stop="sliderChange" @changing="sliderChanging" step="1" :value="sliderValue" backgroundColor="#9f9587" activeColor="#d6d2cc" block-color="#FFFFFF" block-size="12"/>
</view> </view>
<view class="druationTime">{{druationTime}}</view> <view class="druationTime">{{druationTime}}</view>
<view class="druationTime"> <view class="druationTime">
@@ -44,7 +44,7 @@
</view> </view>
</view> </view>
<view class="controller-screen"> <view class="controller-screen">
<image :src="require(fullScreenFlag? './images/back.png':'./images/full.png')" @click='fullScreen'/> <image :src="require(fullScreenFlag? './images/back.png':'./images/full.png')" @click.stop='fullScreen'/>
</view> </view>
</view> </view>
</view> </view>
@@ -59,6 +59,10 @@
type: String, type: String,
require: true require: true
}, },
watermark:{
type: Boolean,
default: true
},
name:{ name:{
type: String, type: String,
default: '' default: ''
@@ -74,7 +78,7 @@
}, },
data() { data() {
return { return {
contrlShow:true,//是否显示进度 contrlShow:false,//是否显示控制
contrlShowTimeout:null,//显示控制条句柄 contrlShowTimeout:null,//显示控制条句柄
videoContext:null,//播放器 videoContext:null,//播放器
fullScreenFlag: false,//是否全屏 fullScreenFlag: false,//是否全屏
@@ -98,7 +102,7 @@
}, },
watch:{ watch:{
url(newVal,oldVal){ url(newVal,oldVal){
this.videoContext.pause(); this.videoContext.stop();
this.playing=false; this.playing=false;
}, },
inittime(newVal,oldVal){ inittime(newVal,oldVal){
@@ -107,14 +111,18 @@
}, },
mounted() { mounted() {
this.initPlayingTime=this.inittime; this.initPlayingTime=this.inittime;
this.videoContext=uni.createVideoContext("myVideo", this); this.videoContext=uni.createVideoContext("xvideoPlayer", this);
}, },
methods: { methods: {
// 全屏+退出全屏 // 全屏+退出全屏
fullScreen(){ fullScreen(){
this.fullScreenFlag ? this.videoContext.exitFullScreen() : this.videoContext.requestFullScreen(); if(this.fullScreenFlag){
// this.fullScreenFlag ? this.bool=true : this.bool=false; this.videoContext.exitFullScreen();
this.fullScreenFlag=!this.fullScreenFlag; this.fullScreenFlag=false;
}else{
this.videoContext.requestFullScreen();
this.fullScreenFlag=true;
}
}, },
// 根据秒获取时间 // 根据秒获取时间
formatSeconds(a) { formatSeconds(a) {
@@ -182,13 +190,47 @@
this.currtime = this.formatSeconds(second); this.currtime = this.formatSeconds(second);
} }
}, },
clickVideo(){
// if(this.contrlShowTimeout!=null){
// window.clearTimeout(this.contrlShowTimeout);
// }
// this.contrlShow=!this.contrlShow;
},
onFullScreen(e) { onFullScreen(e) {
this.fullScreenFlag=e.detail.fullScreen;
let divId='videowatermark';//水印
let full=e.detail.fullScreen;
let divControlId='xplayer-control';
let box=document.getElementById('xvideoPlayer-box');
let control=document.getElementById(divControlId);
let $this=this;
setTimeout(() => {
var div = document.getElementById("xvideoPlayer");
var div1 = div.firstChild;
//水印
if(full){
if($this.watermark){
var div3 = document.createElement("div");
div3.id =divId;
div3.setAttribute("class", "fullmark");
div3.innerHTML='';
for(var i=0;i<4;i++){
div3.innerHTML+='<div style="color:#ffffff;width: 40%;height: 155px;padding-left:60px;padding-top:50px; display: flex;justify-content: center; transform: rotate(-36deg);font-size:20px;">'+$this.userInfo.name+$this.userInfo.code+'</div>';
}
div3.style.cssText = "position:absolute;pointer-events: none; width: 100%;height: 100%;top:0;left:0;bottom: 0;right: 0; display: flex;justify-content: center;flex-wrap: wrap;overflow: hidden; opacity:0.3;padding-top:10px";
div1.appendChild(div3);
}
//添加控制条
div1.appendChild(control);
}else{
var hasControlDiv=div1.querySelector("#"+divControlId);
if(hasControlDiv){
box.appendChild(hasControlDiv);
}
if($this.watermark){
var markDiv=div1.querySelector("#"+divId);
if(markDiv){
div1.removeChild(markDiv);
}
}
}
},200);
this.$emit('fullscreenchange',e); this.$emit('fullscreenchange',e);
//this.fullScreenFlag ? this.videoContext.exitFullScreen() : this.videoContext.requestFullScreen(); //this.fullScreenFlag ? this.videoContext.exitFullScreen() : this.videoContext.requestFullScreen();
// this.fullScreenFlag ? this.bool=true : this.bool=false; // this.fullScreenFlag ? this.bool=true : this.bool=false;
@@ -199,6 +241,16 @@
this.$emit('error',e); this.$emit('error',e);
}, },
onTouchend(e){ onTouchend(e){
if(this.contrlShowTimeout!=null){
window.clearTimeout(this.contrlShowTimeout);
}
if(!this.fullScreenFlag){
this.contrlShow=!this.contrlShow;
}else{
if(!this.contrlShow){
this.contrlShow=show;
}
}
// this.onPlayerPause() // this.onPlayerPause()
// this.touchNum ++ // this.touchNum ++
// let $this=this; // let $this=this;
@@ -222,6 +274,7 @@
onMetaLoad(e){ onMetaLoad(e){
this.curVideo.duration=Number(e.detail.duration); this.curVideo.duration=Number(e.detail.duration);
this.druationTime = this.formatSeconds(this.curVideo.duration); this.druationTime = this.formatSeconds(this.curVideo.duration);
this.contrlShow=true;
this.$emit('loadedmetadata',e); this.$emit('loadedmetadata',e);
}, },
onControlsToggle(e){ onControlsToggle(e){
@@ -231,19 +284,17 @@
onPlay(){ onPlay(){
this.videoContext.play(); this.videoContext.play();
this.playing=true; this.playing=true;
//this.contrlShow=true; let $this=this;
// let $this=this; if(this.contrlShow){
// if(this.contrlShow){ this.contrlShowTimeout=window.setTimeout(function(){
// this.contrlShowTimeout=window.setTimeout(function(){ $this.contrlShow=false;
// $this.contrlShow=false; },5000);
// },5000); }
// }
this.$emit('play') this.$emit('play')
}, },
onPlaying(e){ onTimeUpdate(e){
this.playing=true;
this.videoUpdate(e); this.videoUpdate(e);
this.$emit('playing',e) this.$emit('timeupdate',e)
}, },
onPause() { onPause() {
this.playing=false; this.playing=false;
@@ -263,6 +314,12 @@
height: 100%; height: 100%;
position: relative; position: relative;
} }
.screen{
position: relative;
}
.screen-full{
position:static;
}
.process-container{ .process-container{
width:100%; width:100%;
padding:1% 2% 1% 2%; padding:1% 2% 1% 2%;
@@ -279,7 +336,6 @@
background:rgba(59, 57, 57, 0.2); background:rgba(59, 57, 57, 0.2);
} }
.process-container image{ .process-container image{
display:inline-block;
max-width:30rpx; max-width:30rpx;
max-height:30rpx; max-height:30rpx;
text-align:center; text-align:center;
@@ -289,13 +345,13 @@
height:60rpx; height:60rpx;
margin-bottom:10rpx; margin-bottom:10rpx;
flex:6; flex:6;
max-width:40%; max-width:50%;
} }
.controller-play{ .controller-play{
width: 12%; width: 8%;
} }
.controller-screen{ .controller-screen{
width: 10%;
} }
.currtime{ .currtime{
color: #ffffff; color: #ffffff;
@@ -313,21 +369,6 @@
line-height: 60rpx; line-height: 60rpx;
text-align: center; text-align: center;
} }
.video_back{
display:block;
width:60rpx;
height:60rpx;
left:5rpx;
top:15rpx;
position:absolute;
text-align:center;
z-index:19;
}
.video_back image{
width:44rpx;
height:44rpx;
}
.player-speed{ .player-speed{
position: relative; position: relative;
color: #e5e5e5; color: #e5e5e5;

View File

@@ -9,36 +9,19 @@
<view v-if="curContent.contentType==10" style="background-color: #000000;"> <view v-if="curContent.contentType==10" style="background-color: #000000;">
<!--视频--> <!--视频-->
<view style="position: relative;"> <view style="position: relative;">
<video id="myVideo" <video-player
@touchend="doubleClickVideo" url="/static/temp/test.mp4"
:src="blobUrl" controls
controls :enable-play-gesture="true"
:enable-play-gesture="true" :inittime="curContent.lastStudyTime"
:initial-time="curContent.lastStudyTime" @play="onPlayerPlay"
@play="onPlayerPlay" @pause="onPlayerPause"
@pause="onPlayerPause" @ended="onPlayerEnded"
@ended="onPlayerEnded" @timeupdate="onPlayerPlaying"
@timeupdate="onPlayerPlaying" @fullscreenchange="onFullScreen"
@fullscreenchange="onFullScreen" style="width: 100%; object-fit: fill">
style="width: 100%; object-fit: fill"> ></video-player>
</video> <view class="player-box" v-if="playerBoxShow">
<!--倍速度-->
<view id="myVideoSpeed" class="player-controls-btn cursor-pointer btn-speed">
<view @click="showSpeedCtrl">{{videoSpeed === 1 ? '倍速' : `${videoSpeed}x`}}</view>
<view class="speed-control" v-if="speedListShow">
<view class="speed-control-list">
<view class="li"
v-for="item in speedList"
:key="item"
@click="changeSpeed(item)"
:data-value="item"
:class="{'current': videoSpeed === Number(item)}">
{{ item }}x
</view>
</view>
</view>
</view>
<view class="player-box" v-if="playerBoxShow">
<view class="player-praise"> <view class="player-praise">
<view @click="praiseContent" style="cursor: pointer;"> <view @click="praiseContent" style="cursor: pointer;">
<image class="icon-small" v-if="isPraise" src="/static/images/icon/praise-active.png" /> <image class="icon-small" v-if="isPraise" src="/static/images/icon/praise-active.png" />
@@ -1335,41 +1318,7 @@
}, },
onFullScreen(e){ onFullScreen(e){
//console.log(e,'e'); //console.log(e,'e');
let full=e.detail.fullScreen;
let divId='videowatermark';
setTimeout(() => {
var div = document.getElementById('myVideo')
var div1 = div.firstChild;
var speedDiv=div1.querySelector("#myVideoSpeed");
if(full){
var div3 = document.createElement("div");
div3.id =divId;
div3.setAttribute("class", "fullmark");
div3.innerHTML='';
// 从父组件传过来的水印内容
//div3.innerText =this.userInfo.name+this.userInfo.code;
for(var i=0;i<4;i++){
div3.innerHTML+='<div style="color:#ffffff;width: 40%;height: 155px;padding-left:60px;padding-top:50px; display: flex;justify-content: center; transform: rotate(-36deg);font-size:20px;">'+this.userInfo.name+this.userInfo.code+'</div>';
}
div3.style.cssText = "position:absolute;pointer-events: none; width: 100%;height: 100%;top:0;left:0;bottom: 0;right: 0; display: flex;justify-content: center;flex-wrap: wrap;overflow: hidden; opacity:0.3;padding-top:10px";
//console.log(div3,'div3');
div1.appendChild(div3);
if(!speedDiv){
var speedDiv=document.getElementById('myVideoSpeed');
div1.appendChild(speedDiv)
}
}else{
var markDiv=div1.querySelector("#"+divId);
//var speedDiv=div1.querySelector("#myVideoSpeed");
if(markDiv){
div1.removeChild(markDiv);
}
if(speedDiv){
//div1.removeChild(speedDiv);
}
}
}, 200);
}, },
onPlayerPlay(){ onPlayerPlay(){
this.isPlaying = true; this.isPlaying = true;

View File

@@ -1,6 +1,6 @@
<template> <template>
<view> <view>
<view> <view v-if="show">
<video-player <video-player
:url="fileUrl" :url="fileUrl"
:name="title" :name="title"
@@ -8,14 +8,22 @@
:drag="true" :drag="true"
@play="videoPlay" @play="videoPlay"
@pause="videoPause" @pause="videoPause"
@playing="videoPlaying" @timeupdate="videoPlaying"
@ended="videoEnd" @ended="videoEnd"
@fullscreenchange="videoScreen"> @fullscreenchange="videoScreen">
</video-player> </video-player>
</view> </view>
<!-- <view style="padding-top: 30px;display: flex;justify-content: center;"> <view style="padding-top: 30px;display: flex;justify-content: center;">
<button type="primary" @click="changeSrc">切换测试</button> <button type="default" @click="loadVideo()">加载</button>
</view> --> <button type="primary" @click="changeSrc()">切换测试</button>
</view>
<view>
<video style="width: 100%;"
:src="fileUrl"
:controls="true"
@fullscreenchange="videoScreen"
></video>
</view>
</view> </view>
</template> </template>
@@ -23,25 +31,28 @@
export default{ export default{
data(){ data(){
return { return {
fileUrl:'/static/temp/test.mp4', show:false,
initTime:20, fileUrl:'',
title:'测试播放', initTime:0,
title:'',
author:'', author:'',
} }
}, },
mounted() { mounted() {
//this.startAudioPlay(); this.loadVideo();
}, },
methods:{ methods:{
startAudioPlay(){ loadVideo(){
this.fileUrl='http://localhost:9090/cdn/upload/course/2022/5/979321410778959872.mp3'; //this.fileUrl='http://localhost:9090/cdn/upload/course/2022/5/979321410778959872.mp3';
this.fileUrl='/static/temp/test.mp4';
this.title='标题内容111'; this.title='标题内容111';
this.author='作者信息'; this.initTime=40;
this.show=true;
}, },
changeSrc(){ changeSrc(){
this.fileUrl='http://localhost:9090/cdn/upload/course/2022/4/964853684964700160.mp3'; this.fileUrl='/static/temp/video.mp4';
this.title='标题内容22'; this.title='标题内容221';
this.author='作者信息'; this.initTime=20
}, },
videoPlay(){ videoPlay(){
console.log('videoPlay'); console.log('videoPlay');