这个问题想必好多朋友都遇到过,他的解决方案我的总结就是三种
1:使用nvue,但是我老大说这个可能有兼容问题,我也没有细究,写了个demo,但是最后也没有实际应用
2:使用cover-view解决,我看官网介绍的理解就是通过这个组件作为弹窗可以覆盖掉video标签,但是我没有使用过
3:使用render.js解决,这也是我的最终方案
附代码:
<!-- eslint-disable -->
<template>
<!--
videoSrc 当src变化时修改videoSrc 触发zrender的srcChange 监听播放暂停
eventDrive 将播放状态传递给zrender 可以通过自定义按钮控制播放eventHandle
randomNumChange 赋值唯一id
-->
<view
v-html="videoHtml"
id="dom-video"
class="dom-video"
:eventDrive="eventDrive"
:change:eventDrive="domVideo.eventHandle"
:videoSrc="videoSrc"
:change:videoSrc="domVideo.srcChange"
:randomNum="randomNum"
:change:randomNum="domVideo.randomNumChange"
/>
</template>
<script>
export default {
props: {
src: {
type: String,
default: "",
},
autoplay: {
type: Boolean,
default: false,
},
loop: {
type: Boolean,
default: false,
},
controls: {
type: Boolean,
default: false,
},
objectFit: {
type: String,
default: "contain",
},
muted: {
type: Boolean,
default: false,
},
poster: {
type: String,
default: "",
},
},
// 数据状态
data() {
return {
videoHtml: "",
videoSrc: "",
eventDrive: null, //播放状态
videoProps: {},
randomNum: Math.floor(Math.random() * 100000000 + 1),
};
},
watch: {
// 监听视频资源文件更新
src: {
handler(val) {
if (!val) return;
this.initVideoHtml(); //初始化视频
setTimeout(() => {
this.videoSrc = val;
}, 0);
},
immediate: true,
},
// 监听首次加载
autoplay: {
handler(val) {
this.videoProps.autoplay = val;
},
immediate: true,
},
},
// 生命周期
mounted() {
this.initVideoHtml();
},
// 方法
methods: {
beforeDestroy() {
this.eventDrive = 'stop'
},
// 将video的事件传递给父组件
videoEvent(data) {
// console.log('向父组件传递事件 =>', data)
this.$emit("videoEvent", data);
},
changePlaybackProgress(data) {
this.$emit("changePlaybackProgress", data);
},
// 初始化视频
initVideoHtml() {
//src 视频路径
//autoplay是否自动播放
//loop是否循环播放
//controls是否显示控制栏
//muted是否静音播放
//poster视频封面图
//preload是否在完成页面加载后,载入视频 如果存在autoplay则忽略该属性
//playsinline ios是否默认全屏播放
//webkit-playsinline ios是否默认全屏播放
//webkit-playsinline ios是否默认全屏播放
//controlslist 隐藏控制栏某些功能
this.videoHtml = `<video
src="${this.src}"
id="dom-html-video_${this.randomNum}"
class="dom-html-video"
${this.autoplay ? "autoplay" : ""}
${this.loop ? "loop" : ""}
${this.controls ? "controls" : ""}
${this.muted ? "muted" : ""}
poster="${this.src}?x-oss-process=video/snapshot,t_0,f_jpg"
preload="auto"
playsinline
webkit-playsinline
width="100%"
height="100%"
controlslist="nodownload"
style="object-fit: ${this.objectFit};padding:0;"
>
</video>
`;
// console.log('视频html =>', this.videoHtml)
},
resetEventDrive() {
this.eventDrive = null;
},
},
};
</script>
<script module="domVideo" lang="renderjs">
export default {
data() {
return {
video: null,
timeSetInterval: null,
num: '',
options: {},
}
},
methods: {
myplay() {
this.getPlaybackProgress(true)
this.$ownerInstance.callMethod('videoEvent', 'play')
},
mypause() {
this.getPlaybackProgress(false)
this.$ownerInstance.callMethod('videoEvent', 'pause')
},
myended() {
this.getPlaybackProgress(false)
this.$ownerInstance.callMethod('videoEvent', 'ended')
this.$ownerInstance.callMethod('resetEventDrive')
},
initVideoEvent() {
setTimeout(() => {
let video = document.getElementById(`dom-html-video_${this.num}`)
this.video = video
// 将之前的视频事件移出监听
video.removeEventListener("play", this.myplay)
video.removeEventListener("pause", this.mypause)
video.removeEventListener("ended", this.myended)
// 监听视频事件/重新监听视频事件
video.addEventListener('play', this.myplay)
video.addEventListener('pause', this.mypause)
video.addEventListener('ended', this.myended)
}, 100)
// this.getPlaybackProgress(false)
},
eventHandle(eventType) {
if (eventType) {
this.video = document.getElementById(`dom-html-video_${this.num}`)
if (eventType === 'play') {
setTimeout(() => {
this.video.play();
}, 350)
return
} else if (eventType === 'pause') {
setTimeout(() => {
this.video.pause();
this.timeSetInterval && clearInterval(this.timeSetInterval)
}, 350)
} else if (eventType === 'stop') {
this.video.stop()
this.timeSetInterval && clearInterval(this.timeSetInterval)
}
}
},
srcChange(val) {
this.video = document.getElementById(`dom-html-video_${this.num}`)
// 实现视频的第一帧作为封面,避免视频展示黑屏
this.initVideoEvent() //监听播放暂停事件
// setTimeout(() => {
// let video = document.getElementById(`dom-html-video_${this.num}`)
// video.addEventListener('loadedmetadata', () => {
// let {
// autoplay
// } = this.options
// // video.play()
// // if (!autoplay) {
// // video.pause()
// // }
// })
// }, 10)
},
randomNumChange(val) {
this.num = val
},
getPlaybackProgress(bool) { // 监听播放状态
// console.log(bool)
if (bool) {
this.timeSetInterval = setInterval(() => {
let currentTime = this.video.currentTime
let duration = this.video.duration
this.$ownerInstance.callMethod('changePlaybackProgress', {
currentTime,
duration
})
}, 1000)
} else {
clearInterval(this.timeSetInterval)
this.timeSetInterval = null
}
// console.log(time)
// clearInterval(this.timeSetInterval)
// this.timeSetInterval = null
// this.timeSetInterval = setInterval(() => {
// let currentTime = this.video.currentTime
// let duration = this.video.duration
// this.$ownerInstance.callMethod('changePlaybackProgress', {
// currentTime,
// duration
// })
// }, time)
// else {
// clearInterval(this.timeSetInterval)
// this.timeSetInterval = null
// }
},
}
}
</script>
<style lang="scss" scoped>
.dom-video {
overflow: hidden;
height: 100%;
padding: 0;
&-height {
height: 100%;
}
}
</style>