mirror of
https://codeup.aliyun.com/67762337eccfc218f6110e0e/vue/learning-system-mobile.git
synced 2025-12-09 02:46:46 +08:00
视频器拖动调整
This commit is contained in:
170
components/video-player/progress-bar.vue
Normal file
170
components/video-player/progress-bar.vue
Normal file
@@ -0,0 +1,170 @@
|
||||
/**
|
||||
$emit: updateProgress, -> 调整进度条后触发的事件,传递参数:currentProgress
|
||||
getMouseDownStatus, -> 获取是否鼠标按下的状态,传递参数:true/false
|
||||
props: width, height,
|
||||
currentProgress, -> 当前进度,范围0-1
|
||||
*/
|
||||
<template>
|
||||
<div
|
||||
class="progress-bar"
|
||||
:style="{width: width}"
|
||||
@mousedown.left="down"
|
||||
@mousemove="move"
|
||||
@mouseup="up"
|
||||
>
|
||||
<div class="progress-full" :style="{height: height}">
|
||||
<div class="progress-current" :style="{width: currentProgress + '%'}"></div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "progress-bar",
|
||||
props: {
|
||||
width: {
|
||||
type: String,
|
||||
default: "100%",
|
||||
},
|
||||
height: {
|
||||
type: String,
|
||||
default: "4px",
|
||||
},
|
||||
// 当前进度,范围0-1
|
||||
currentProgress: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
isDrag:{
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
blobId:{
|
||||
type: String,
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
is_mousedown_progress: false, //是否点击了进度条并保持点击状态
|
||||
current_width_px: 0, // 当前进度条的像素长度
|
||||
init_clientX: 0, //初始进度的偏移量,相对于视口
|
||||
dom_full: null, //完整进度条的dom,即进度条背景
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
//console.log(this.isDrag,'isDrag');
|
||||
//初始化一些固定数据
|
||||
let dom_full = this.$el.getElementsByClassName("progress-full")[0];
|
||||
this.dom_full = dom_full;
|
||||
//绑定全局监听器
|
||||
window.addEventListener("touchmove", (e) => {
|
||||
if (this.is_mousedown_progress) {
|
||||
this.move(e);
|
||||
}
|
||||
});
|
||||
window.addEventListener("touchend", (e) => {
|
||||
this.up(e);
|
||||
});
|
||||
},
|
||||
beforeDestroy() {
|
||||
//
|
||||
},
|
||||
methods: {
|
||||
down(e) {
|
||||
|
||||
this.$emit("getMouseDownStatus", true);
|
||||
this.is_mousedown_progress = true;
|
||||
// 获取完整进度条的clientX(dom左上角)
|
||||
let init_clientX = this.dom_full.getBoundingClientRect().left;
|
||||
// 计算调整后的当前进度条的长度
|
||||
this.current_width_px = e.clientX - init_clientX;
|
||||
// 设置当前的播放进度(同时作用于当前进度条的样式)
|
||||
let current = (e.clientX - init_clientX) / this.dom_full.clientWidth;
|
||||
var time = localStorage.getItem('videoProgressData');
|
||||
var arr = time&&JSON.parse(time) || {}
|
||||
console.log('down::',this.isDrag,time,arr[this.blobId] ,current)
|
||||
// 禁止拖动
|
||||
if(!this.isDrag && time && arr[this.blobId] < current) return;
|
||||
|
||||
this.$emit("updateProgress", current);
|
||||
},
|
||||
move(e) {
|
||||
if (this.is_mousedown_progress) {
|
||||
let init_clientX = this.dom_full.getBoundingClientRect().left;
|
||||
this.current_width_px = e.clientX - init_clientX;
|
||||
let current = (e.clientX - init_clientX) / this.dom_full.clientWidth;
|
||||
var time = localStorage.getItem('videoProgressData');
|
||||
var arr = time&&JSON.parse(time) || {}
|
||||
console.log('move::',this.isDrag,time,arr[this.blobId] ,current)
|
||||
// 禁止拖动
|
||||
if(!this.isDrag && time && arr[this.blobId] < current) return;
|
||||
this.$emit("updateProgress", current);
|
||||
}
|
||||
},
|
||||
up() {
|
||||
if (this.is_mousedown_progress) {
|
||||
// 标记鼠标不处于按下的状态了
|
||||
this.is_mousedown_progress = false;
|
||||
this.$emit("getMouseDownStatus", false);
|
||||
// 松开鼠标后,即调整进度条后,此时的进度(0-1)
|
||||
let current = this.current_width_px / this.dom_full.clientWidth;
|
||||
var time = localStorage.getItem('videoProgressData');
|
||||
var arr = time&&JSON.parse(time) || {}
|
||||
console.log('up::',this.isDrag,time,arr[this.blobId] ,current)
|
||||
// 禁止拖动
|
||||
if(!this.isDrag && time && arr[this.blobId] < current) return;
|
||||
this.$emit("updateProgress", current);
|
||||
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.progress-bar {
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
padding: 2px 0;
|
||||
margin: 0;
|
||||
transition: height 0.2s;
|
||||
/*overflow: hidden;*/
|
||||
}
|
||||
.progress-bar:hover .progress-full {
|
||||
height: 2px !important;
|
||||
}
|
||||
.progress-full {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
background: rgb(201, 201, 201);
|
||||
transition: height 0.3s;
|
||||
}
|
||||
.progress-current {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
height: inherit;
|
||||
width: 50%;
|
||||
display: inline-block;
|
||||
background-color: var(--primaryColor);
|
||||
}
|
||||
.progress-current::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
display: inline-block;
|
||||
right: 0;
|
||||
top: 50%;
|
||||
bottom: 50%;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
border-radius: 100%;
|
||||
background: #fff;
|
||||
transform: translate(50%, -50%);
|
||||
opacity: 1;
|
||||
transition: opacity 0.3s;
|
||||
}
|
||||
.progress-bar:hover .progress-current::after {
|
||||
opacity: 1;
|
||||
}
|
||||
</style>
|
||||
@@ -22,9 +22,22 @@
|
||||
<image :src="require(playing? './images/pause.png':'./images/play.png')" @click.stop='videoOpreation'/>
|
||||
</view>
|
||||
<view class="currtime">{{currtime}}</view>
|
||||
<view class='slider-container'>
|
||||
<slider :disabled="!drag" @change.stop="sliderChange" @changing="sliderChanging" step="1" :value="sliderValue" backgroundColor="#9f9587" activeColor="#d6d2cc" block-color="#FFFFFF" block-size="12"/>
|
||||
<!-- <cover-view v-if="drag" class='slider-container'>
|
||||
<slider @change.stop="sliderChange" @changing="sliderChanging" step="1" :value="sliderValue" backgroundColor="#9f9587" activeColor="#d6d2cc" block-color="#FFFFFF" block-size="12"/>
|
||||
<slider v-if="!drag" disabled="true" step="1" :value="sliderValue" backgroundColor="#9f9587" activeColor="#d6d2cc" block-color="#FFFFFF" block-size="12"/>
|
||||
</cover-view> v-if="!drag" -->
|
||||
<view class='slider-container new-bar'>
|
||||
<progressBar
|
||||
:currentProgress="sliderValue"
|
||||
:blobId="blobId"
|
||||
v-on:updateProgress="updateProgressByClickBar"
|
||||
v-on:getMouseDownStatus="getMouseDownStatusOfProgressBar"
|
||||
:isDrag="drag"
|
||||
width="100%"
|
||||
></progressBar>
|
||||
</view>
|
||||
|
||||
|
||||
<view class="druationTime">{{druationTime}}</view>
|
||||
<view class="druationTime">
|
||||
<view id="myVideoSpeed" class="player-speed btn-speed">
|
||||
@@ -51,14 +64,21 @@
|
||||
</view>
|
||||
</template>
|
||||
<script>
|
||||
import progressBar from "@/components/video-player/progress-bar.vue";
|
||||
import {mapGetters} from 'vuex'
|
||||
import studyUtil from '@/utils/study.js';
|
||||
export default {
|
||||
components: { progressBar },
|
||||
props: {
|
||||
url:{
|
||||
type: String,
|
||||
require: true
|
||||
},
|
||||
// 视频链接对应的content Id
|
||||
blobId: {
|
||||
type: String,
|
||||
default: null,
|
||||
},
|
||||
watermark:{
|
||||
type: Boolean,
|
||||
default: true
|
||||
@@ -89,12 +109,15 @@
|
||||
updateState: true, //防止视频播放过程中导致的拖拽失效
|
||||
playing:false,//是否在播放中
|
||||
curVideo:{
|
||||
duration:0
|
||||
duration:0,
|
||||
currentTime: 0
|
||||
},
|
||||
touchNum:0,
|
||||
speedListShow:false,
|
||||
speedList:["2.0", "1.5", "1.25", "1.0", "0.75", "0.5"],
|
||||
videoSpeed: 1.0, // 当前倍速:
|
||||
isMousedownProgress: false, // 鼠标是否按下了进度条(并未松开)
|
||||
historyTime: 0 // 当前视频
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
@@ -114,6 +137,36 @@
|
||||
this.videoContext=uni.createVideoContext("xvideoPlayer", this);
|
||||
},
|
||||
methods: {
|
||||
/* 点击进度条更新视频播放进度
|
||||
*/
|
||||
updateProgressByClickBar(value) {
|
||||
console.log('value------:',value)
|
||||
let duration = this.curVideo.duration;
|
||||
|
||||
let new_current_time = Math.round(value * duration);
|
||||
// this.barrageTimelineStart = new_current_time;
|
||||
this.curVideo.currentTime = new_current_time;
|
||||
this.sliderValue = value * 100;
|
||||
this.videoContext.seek(new_current_time);
|
||||
|
||||
|
||||
// var duration=this.curVideo.duration;
|
||||
// var second=e.detail.value / 100 * duration;
|
||||
// if (duration) { //完成拖动后,计算对应时间并跳转到指定位置
|
||||
// this.videoContext.seek(second);
|
||||
// this.sliderValue= e.detail.value,
|
||||
// this.updateState= true //完成拖动后允许更新滚动条
|
||||
// this.druationTime = this.formatSeconds(duration);
|
||||
// this.currtime = this.formatSeconds(second);
|
||||
// }
|
||||
|
||||
|
||||
},
|
||||
/* 获取鼠标是否按下了进度条
|
||||
*/
|
||||
getMouseDownStatusOfProgressBar(value) {
|
||||
this.isMousedownProgress = value;
|
||||
},
|
||||
// 全屏+退出全屏
|
||||
fullScreen(){
|
||||
if(this.fullScreenFlag){
|
||||
@@ -161,18 +214,50 @@
|
||||
},
|
||||
// 播放进度变化时触发,event.detail = {currentTime, duration} 。触发频率 250ms 一次
|
||||
videoUpdate(e) {
|
||||
|
||||
this.historyTime = e.detail.currentTime
|
||||
|
||||
let duration=this.curVideo.duration;
|
||||
let sliderValue = e.detail.currentTime / duration * 100;
|
||||
let second=sliderValue / 100 * duration;
|
||||
|
||||
// console.log('onTimeUpdate11111::',this.drag,second)
|
||||
// if(!this.drag){
|
||||
// this.videoContext.seek(second);
|
||||
// return;
|
||||
// }
|
||||
|
||||
|
||||
|
||||
if (this.updateState) { //判断拖拽完成后才触发更新,避免拖拽失效
|
||||
this.sliderValue=sliderValue;
|
||||
this.$emit('progress',this.sliderValue);
|
||||
}else{
|
||||
|
||||
}
|
||||
// alert(this.sliderValue)
|
||||
this.druationTime = this.formatSeconds(duration);
|
||||
//console.log(this.druationTime,'this.druationTime');
|
||||
this.currtime = this.formatSeconds(second);
|
||||
|
||||
// var time = localStorage.getItem('videoProgressData')
|
||||
// //alert(1)
|
||||
// if(time && !this.drag || !this.drag && !time ){
|
||||
// var arr = time&&JSON.parse(time) || {}
|
||||
// if(arr[this.url] < this.sliderValue/100 || !arr[this.url]){
|
||||
// arr[this.url] = this.sliderValue/100
|
||||
// localStorage.setItem('videoProgressData',JSON.stringify(arr))
|
||||
// }
|
||||
// }
|
||||
// 视频播放时本地记录视频实时播放时长,视频设置了禁止拖动时执行
|
||||
if(!this.drag){
|
||||
var time = localStorage.getItem('videoProgressData')
|
||||
var arr = time&&JSON.parse(time) || {}
|
||||
if(arr[this.blobId] < this.sliderValue/100 || !arr[this.blobId]){
|
||||
arr[this.blobId] = parseFloat((this.sliderValue/100).toFixed(8))
|
||||
if(arr[this.blobId]) localStorage.setItem('videoProgressData',JSON.stringify(arr))
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
//拖动过程中触发的事件
|
||||
sliderChanging(e) {
|
||||
@@ -249,7 +334,7 @@
|
||||
this.contrlShow=!this.contrlShow;
|
||||
}else{
|
||||
if(!this.contrlShow){
|
||||
this.contrlShow=show;
|
||||
this.contrlShow=true;
|
||||
}
|
||||
}
|
||||
// this.onPlayerPause()
|
||||
@@ -348,6 +433,9 @@
|
||||
flex:6;
|
||||
max-width:50%;
|
||||
}
|
||||
.slider-container.new-bar{
|
||||
margin: 7px 10px 10px 10px;
|
||||
}
|
||||
.controller-play{
|
||||
width: 8%;
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
<view style="position: relative;">
|
||||
<video-player
|
||||
:url="blobUrl"
|
||||
:blobId="blobId"
|
||||
controls
|
||||
:enable-play-gesture="true"
|
||||
:inittime="curContent.lastStudyTime"
|
||||
@@ -20,7 +21,6 @@
|
||||
@timeupdate="onPlayerPlaying"
|
||||
@fullscreenchange="onFullScreen"
|
||||
:drag="curriculumData.isDrag"
|
||||
@progress="progress"
|
||||
style="width: 100%; object-fit: fill">
|
||||
></video-player>
|
||||
<view class="player-box" v-if="playerBoxShow">
|
||||
@@ -428,9 +428,6 @@
|
||||
export default {
|
||||
data(){
|
||||
return{
|
||||
progressData: 0,
|
||||
contentTypeV: '',
|
||||
trueFalse: true,
|
||||
loading:false,//加载中
|
||||
courseId:'',//当前课程的id
|
||||
studyId: '',//当前学习的id
|
||||
@@ -486,6 +483,7 @@
|
||||
appentInterval:15,//追加学习时间的间隔 3秒加一次
|
||||
preTime:-1,
|
||||
blobUrl:'',//音视频的播放地址
|
||||
blobId: '',
|
||||
localTimeKey:'boeu-study-time' ,//本地存储的学习时长的key json格式
|
||||
localTimeValue:0,//计算的时间
|
||||
appendStudyOtherHandle:null,
|
||||
@@ -630,7 +628,6 @@
|
||||
let $this=this;
|
||||
uni.showLoading({title:'加载中...'})
|
||||
apiCourseStudy.studyIndex(this.courseId).then(rs=>{
|
||||
// this.courseType = rs.result.course.type
|
||||
if(rs.status != 200) {
|
||||
uni.hideLoading();
|
||||
uni.showToast({title:rs.message,type:'fail'});
|
||||
@@ -777,6 +774,22 @@
|
||||
});
|
||||
},
|
||||
playContent(con,conIndex,catIndex){
|
||||
|
||||
// 视频设置禁用处理逻辑,如果用户已全部观看完该视频,则设置为能全部拖动的逻辑,把isDrag设置为true即可,同时删除本地存储的数据
|
||||
|
||||
// if(con.progressVideo ===1){
|
||||
// var obj = JSON.parse(con.content)
|
||||
// obj.isDrag = true
|
||||
// con.content = JSON.stringify(obj)
|
||||
|
||||
// var time = localStorage.getItem('videoProgressData')
|
||||
// var arr = time&&JSON.parse(time) || {}
|
||||
// alert(con.progressVideo+'--'+con.id + '--'+JSON.stringify(arr))
|
||||
// delete arr[con.id];
|
||||
// localStorage.setItem('videoProgressData',JSON.stringify(arr))
|
||||
|
||||
// }
|
||||
console.log('更换播放内容 playContent::',con,conIndex,catIndex)
|
||||
//对于需要控制学习顺序的
|
||||
if(conIndex!=undefined && catIndex!=undefined) {
|
||||
if(this.courseInfo.orderStudy) {
|
||||
@@ -798,6 +811,7 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//切换播放内容
|
||||
this.changePlayRes(con);
|
||||
},
|
||||
@@ -884,7 +898,6 @@
|
||||
//this.curContent=0;
|
||||
// console.log(con,'con');
|
||||
this.playerBoxShow=false;
|
||||
this.contentTypeV = con.contentType
|
||||
if(con.contentType==40){
|
||||
//如果是文档,需要再次加载pdf
|
||||
if(con.content!='' && con.content.indexOf('.pdf')==-1){
|
||||
@@ -936,13 +949,16 @@
|
||||
location.href=this.conLink.url
|
||||
}
|
||||
} else if(con.contentType==10 || con.contentType==20) {
|
||||
|
||||
if(con.content.startsWith('\{')){
|
||||
this.curriculumData=JSON.parse(con.content);
|
||||
var d = JSON.parse(con.content)
|
||||
if(d.url=="/course/2024/4/1224670812274712576.mp4") d.isDrag = false
|
||||
this.curriculumData=d;
|
||||
}else{
|
||||
this.curriculumData.url=con.content;
|
||||
}
|
||||
console.log('this.curriculumData:::',this.curriculumData)
|
||||
this.blobUrl=this.fileBaseUrl+this.curriculumData.url;
|
||||
this.blobId = con.id
|
||||
//console.log(this.blobUrl,'this.blobUrl');
|
||||
}
|
||||
//console.log(con.contentType,'con.contentType');
|
||||
@@ -1300,9 +1316,6 @@
|
||||
//console.log(e);
|
||||
this.scrollInfo = e.detail;
|
||||
},
|
||||
progress(val) {
|
||||
this.progressData = (val).toFixed(2);
|
||||
},
|
||||
//以下是播放相关的处理
|
||||
saveStudyDuration(duration) { //保存本地存储的学习时长
|
||||
if (duration > 0) {
|
||||
@@ -1319,12 +1332,8 @@
|
||||
"objInfo": ""+this.courseInfo.name,
|
||||
"aid":this.userInfo.aid, //当前登录人的id
|
||||
"aname":this.userInfo.name,//当前人的姓名
|
||||
"status": 1, //状态
|
||||
"contentId": this.curContent.id,
|
||||
"status": 1 //状态
|
||||
}
|
||||
if(this.contentTypeV == 10) {
|
||||
postData.progress = this.progressData
|
||||
}
|
||||
//静默处理
|
||||
apiStat.sendEvent(postData).then(rs=>{
|
||||
if(rs.status == 200) {
|
||||
@@ -1538,20 +1547,6 @@
|
||||
}
|
||||
},
|
||||
onPlayerPlaying(e){
|
||||
if(e.detail.currentTime > 2 && this.trueFalse){
|
||||
let params ={
|
||||
studyId: this.studyId,//学习id,
|
||||
courseId: this.courseId,//课程id,
|
||||
contentId: this.curContent.id,//内容id,
|
||||
contentType: this.curContent.contentType,
|
||||
contentName: this.curContent.contentName,//内容名称
|
||||
progress: 1,
|
||||
status: 2,
|
||||
contentTotal:this.totalContent
|
||||
}
|
||||
apiCourseStudy.studyContent(params)
|
||||
this.trueFalse = false
|
||||
}
|
||||
//console.log("当前播放11",itme);
|
||||
//console.log("当前播放11"+itme);
|
||||
let intTime=parseInt(e.detail.currentTime);
|
||||
@@ -1591,6 +1586,18 @@
|
||||
itemId:this.curContent.studyItemId,
|
||||
videoTime:intTime
|
||||
}
|
||||
|
||||
//alert(3+'--'+this.curriculumData.isDrag +'---'+this.curContent.progressVideo)
|
||||
if(!this.curriculumData.isDrag && this.curContent.progressVideo !=1){
|
||||
var time = localStorage.getItem('videoProgressData')
|
||||
var arr = time&&JSON.parse(time) || {}
|
||||
if(arr[this.blobId]) {
|
||||
postData.progressVideo = arr[this.blobId]
|
||||
postData.contentId = this.curContent.id
|
||||
postData.courseId = this.curContent.courseId
|
||||
}
|
||||
}
|
||||
|
||||
apiCourseStudy.studyVideoTime(postData).then(rs=>{
|
||||
if(rs.status!=200){
|
||||
console.log('记录播放时间错误');
|
||||
@@ -1662,6 +1669,15 @@
|
||||
itemId:this.curContent.studyItemId,
|
||||
videoTime:intTime
|
||||
}
|
||||
if(!this.curriculumData.isDrag && this.curContent.progressVideo !=1){
|
||||
var time = localStorage.getItem('videoProgressData')
|
||||
var arr = time&&JSON.parse(time) || {}
|
||||
if(arr[this.blobId]) {
|
||||
postData.progressVideo = arr[this.blobId]
|
||||
postData.contentId = this.curContent.id
|
||||
postData.courseId = this.curContent.courseId
|
||||
}
|
||||
}
|
||||
apiCourseStudy.studyVideoTime(postData).then(rs=>{
|
||||
if(rs.status!=200){
|
||||
console.log('记录播放时间错误');
|
||||
|
||||
Reference in New Issue
Block a user