欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

项目中的视频标记实践、属性和事件详情

最编程 2024-04-09 18:17:32
...

前言

  • 新年开工第一天,祝大家新年快乐、虎年大吉、技术和工资蹭蹭涨、代码 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 网速失速
play play()和autoplay开始播放时触发
pause pause()触发
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 的播放器。

参考链接

  • w3c 事件 Media 事件
  • h5 video方法,事件,属性详解

往期精彩

  • 磕磕绊绊的 4 年前端er,一次含泪总结
  • 前端还不会 Nginx 吗?快来学起来
  • VS Code 提升开发效率、质量以及编码体验指南
  • 金九前端面试总结!
  • 从0搭建Vite + Vue3 + Element-Plus + Vue-Router + ESLint + husky + lint-staged
  • 「前端进阶」JavaScript手写方法/使用技巧自查
  • 公众号打开小程序最佳解决方案(Vue)
  • Axios你可能不知道使用方式

「点赞、收藏和评论」

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