uniapp解决视频层级过深遮盖弹窗

这个问题想必好多朋友都遇到过,他的解决方案我的总结就是三种 

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>

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值