video 标签在项目中实战、属性及事件详解

3,037 阅读5分钟

前言

  • 新年开工第一天,祝大家新年快乐、虎年大吉、技术和工资蹭蹭涨、代码 bug 蹭蹭没,万事如意!🎉🎉🎉
  • video 标签大家应该都很熟悉了,那有没有遇到些什么问题呢?年前在做一个活动页面的时候,需要放一个视频在上面,本以为是一个很简单的功能,结果最后却是其他功能都实现了,这个视频播放还有各种问题。

遇到的问题

  • iOS 视频无法自动播放;
  • iOS 视频点击播放会自动全屏;
  • 外部链接(微信中),iOS 无法监听事件;
  • 点击播放时,视频区域会出现白屏;
  • 原生的 UI 样式太丑,需要弃掉并按 UI 设计重新写。

了解 video 属性及事件

  • 在解决上面的问题之前,我们需要先了解 video 标签有哪些属性以及事件,我们要用到哪些来解决上面的问题。

HTML 属性

  • 全局属性(所有 HTML 元素一起使用的属性)。
  • 其他属性
    1. src: 要播放的视频的 URL
    2. controls: 如果出现该属性,则向用户显示控件,比如播放按钮。
    3. poster: 规定视频下载时显示的图像,或者在用户点击播放按钮前显示的图像。
    4. autoplay: 如果出现该属性,则视频在就绪后马上播放。
    5. preload: 如果出现该属性,则视频在页面加载时进行加载,并预备播放。如果使用 "autoplay",则忽略该属性。
    6. loop: 如果出现该属性,则当媒介文件完成播放后再次开始播放。
    7. muted: 规定视频的音频输出应该被静音。
    8. poster: 规定视频下载时显示的图像,或者在用户点击播放按钮前显示的图像。
    9. playsinline、webkit-playsinline: 小窗播放。

实例属性

属性名属性含义
currentSrc当前视频地址
currentTime视频已播放时间
videoWidth视频本身的宽度
videoHeight视频本身的高度
duration视频长度,流返回无限
ended是否播放结束
error媒体错误(null:正常)
paused是否停止
muted是否静音
seeking是否在seeking
volume音量
height播放框的高度
width播放框的宽度
startTime开始时间,默认为0
defaultPlaybackRate默认回放速度
playbackRate当前播放速度

video 事件

事件名事件含义
loadstart客户端开始请求数据
progress客户端正在请求数据
suspend延迟下载
abort客户端主动终止下载(不是因为错误引起)
error请求数据时遇到错误
stalled网速失速
playplay()和autoplay开始播放时触发
pausepause()触发
loadedmetadata成功获取资源长度
loadeddata媒介数据已加载时运行的脚本
waiting等待数据,并非错误
playing开始回放
canplay可以播放,但中途可能因为加载而暂停
canplaythrough可以播放,视频全部加载完毕
seeking寻找中
seeked寻找完毕
timeupdate播放时间改变
ended播放结束
ratechange播放速率改变
durationchange资源长度改变
volumechange音量改变

问题解决

  • 通告前面的介绍,相信就算没用过 video 标签的小伙伴也有一定的了解了,针对遇到的问题,我们要用到哪些呢?下面是基本的一些属性:
<video
    ref="videoRef"
    class="video"
    controls
    autoplay
    poster="https://xxx.png"
/>

iOS 视频无法自动播放

  • 去掉 video 标签上的 autoplay 属性。
  • mounted中设置 video 的视频 src 并执行 load 方法,通过添加事件,监听视屏的加载,触发事例的播放事件。
  • 当在初始化时给视频上方盖一个遮罩层,当视频可以播放时,隐藏遮罩层。
mounted() {
    const videoDom = this.$refs.videoRef;
    videoDom.src = 'https://xxx.mp4';
    videoDom.load();
    videoDom.addEventListener('canplay', this.canPlayVideo);
},
methods: {
    canPlayVideo() {
        const videoDom = this.$refs?.videoRef;
        if (!videoDom) return;
        if (videoDom.currentTime > 0) {
            videoDom.currentTime = 0;
        }
        videoDom.play();
        this.videoLoading = false;
        this.isPaused = videoDom.paused; // 后续 UI 样式
        videoDom.removeEventListener('canplay', this.canPlayVideo);
    },
},

iOS 视频点击播放会自动全屏

  • 给 video 标签添加playsinline、webkit-playsinline 属性。
<video
    ref="videoRef"
    class="video"
    preload="auto"
    controls
    playsinline
    webkit-playsinline
    poster="https://xxx.png"
/>

外部链接(微信中),iOS 无法监听事件

方法一
  • 由于无法监听事件,那就不用自动播放,在第一个问题中直接去掉 autoplay(多端一致),或者保留,能自动播放就自动播放。
方法二
  • 引入微信 jssdk<script src="http://res.wx.qq.com/open/js/jweixin-1.0.0.js"></script>
const video = document.querySelectorAll("video")[0]
document.addEventListener("WeixinJSBridgeReady", function () {
     video.play()
}, false)

点击播放时,视频区域会出现白屏

  • video 添加一个背景图片,最好和视频的封面图(videoposter 属性)一致。
.video {
    ...;
    background-image: url('https://xxx.png');
}

原生的 UI 样式太丑,需要弃掉并按 UI 设计重新写

  • 去掉 video 标签的 controls 属性,通过一个遮罩将操作的按钮盖在视频 UI 设计的对应区域是,并给对应的元素绑定对应操作的事件即可。以播放暂停为例:
----- vue html -----
<div v-if="isPaused && !videoLoading" class="video-wrapper" @click="videoPlayer">
    <img class="play-img" src="https://xxx.png" alt="" />
</div>
----- vue js -----
mounted() {
    videoDom.addEventListener('canplay', this.canPlayVideo);
+   videoDom.addEventListener('play', this.videoEvent);
+   videoDom.addEventListener('pause', this.videoEvent);
},
methods: {
    videoEvent() {
        if (this.$refs?.videoRef?.paused) {
            this.isPaused = true;
        } else {
            this.videoLoading = false;
            this.isPaused = false;
        }
    },
    // 点击遮罩的播放按钮
    videoPlayer() {
        if (this.videoLoading) return;
        if (this.$refs?.videoRef?.paused) {
            this.isPaused = false;
            this.$refs.videoRef.play();
        } else {
            this.isPaused = true;
            this.$refs.videoRef.pause();
        }
    },
}
  • 当然,除了上面这些,如果涉及到切换 tab、后台运行等情况也是需要考虑的。

感悟

  • 大多数遇到的问题,我们都可以通过曲线救国的方式去解决,不要一开始就去死磕一个方向走进误区;
  • 通过查阅官方文档、标准等去了解,有时候比直接找一些随便搬运的博客有效;
  • 有兴趣的小伙伴可以自己完全自定义实现一个 video 的播放器。

参考链接

往期精彩

「点赞、收藏和评论」

❤️关注+点赞收藏+评论+分享❤️,手留余香,谢谢🙏大家。