H5端齐采药项目,uniapp框架
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

228 lines
4.9 KiB

<template>
<view v-html="videoHtml" id="dom-video" class="dom-video" :eventDrive="eventDrive"
:change:eventDrive="domVideo.eventHandle" :videoSrc="videoSrc" :change:videoSrc="domVideo.srcChange"
:videoProps="videoProps" :change:videoProps="domVideo.propsChange" :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()
},
beforeDestroy() {
this.videoHtml = ''
},
// 方法
methods: {
// 将video的事件传递给父组件
listener(data) {
console.log('向父组件传递事件 =>', data)
this.$emit('listener', data)
},
// 初始化视频
initVideoHtml() {
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' : ''}
${this.poster ? 'poster="' + this.poster + '"' : ''}
preload="auto"
playsinline
webkit-playsinline
width="100%"
height="100%"
style="object-fit: ${this.objectFit};padding:0;"
>
<source src="${this.src}" type="video/mp4">
<source src="${this.src}" type="video/ogg">
<source src="${this.src}" type="video/webm">
</video>
`
// console.log('视频html =>', this.videoHtml)
},
resetEventDrive() {
this.eventDrive = null
},
// 将service层的事件/数据 => 传递给renderjs层
play() {
this.eventDrive = 'play'
},
pause() {
this.eventDrive = 'pause'
},
stop() {
this.eventDrive = 'stop'
}
}
}
</script>
<script module="domVideo" lang="renderjs">
export default {
data() {
return {
video: null,
num: '',
options: {},
}
},
mounted() {
this.initVideoEvent()
},
methods: {
initVideoEvent() {
setTimeout(() => {
let video = document.getElementById(`dom-html-video_${this.num}`)
this.video = video
// 监听视频事件
video.addEventListener('play', () => {
this.$ownerInstance.callMethod('listener', {
name: 'play',
currentTime: 0,
duration: this.video.duration
})
})
video.addEventListener('pause', () => {
this.$ownerInstance.callMethod('listener', {
name: 'pause',
currentTime: this.video.currentTime,
duration: this.video.duration
})
})
video.addEventListener('ended', () => {
this.$ownerInstance.callMethod('listener', {
name: 'ended',
currentTime: this.video.currentTime,
duration: this.video.duration
})
this.$ownerInstance.callMethod('resetEventDrive')
})
}, 100)
},
eventHandle(eventType) {
if (eventType) {
this.video = document.getElementById(`dom-html-video_${this.num}`)
if (!this.video) {
console.error(`Cannot find video element with id: dom-html-video_${this.num}`);
return;
}
if (eventType === 'play') {
this.video.play()
} else if (eventType === 'pause') {
this.video.pause()
} else if (eventType === 'stop') {
this.video.pause()
this.video.currentTime = 0;
}
}
},
srcChange(val) {
// 实现视频的第一帧作为封面,避免视频展示黑屏
// this.initVideoEvent()
setTimeout(() => {
let video = document.getElementById(`dom-html-video_${this.num}`)
video.addEventListener('loadedmetadata', () => {
console.log('this.options', this.options)
let { autoplay } = this.options
if (!autoplay) {
video.pause()
} else {
video.play()
}
})
}, 100)
},
propsChange(obj) {
this.options = obj
},
randomNumChange(val) {
this.num = val
},
}
}
</script>
<style lang="scss" scoped>
.dom-video {
overflow: hidden;
height: 100%;
padding: 0;
&-height {
height: 100%;
}
}
</style>