赞
踩
在当今数字化时代,视频已成为传递信息、娱乐和教育的重要形式。而HTML5视频标签的出现为网页开发者提供了一种简单且强大的方式来嵌入视频内容到网页中。通过使用HTML5视频标签,我们可以轻松地在网页上播放视频,而不再依赖于第三方插件或特定的浏览器。
然而,仅仅使用video标签并不足以满足复杂的需求和用户交互。为了达到更好的用户体验和功能性,我们需要深入理解HTML5视频标签的各种属性、事件以及播放控制和交互技巧。
本篇博客旨在帮助读者深入理解HTML5视频标签,掌握全方位的播放控制和交互技巧。我们将详细介绍video标签的常用属性,如autoplay、controls、loop等,以及如何实现自定义播放器样式和控制按钮。此外,我们还将探讨视频的加载和预加载、全屏播放、跳转到指定时间点以及实现字幕等高级技巧。
<video src="video.mp4"></video>
解析视频格式:浏览器首先通过src属性指定的URL获取视频文件,并根据文件扩展名确定视频的格式(例如.mp4、.webm、.ogg等)。
创建视频元素:浏览器会创建一个视频元素(HTMLVideoElement),并将其插入到页面的DOM结构中。视频元素可以通过JavaScript来操作和控制。
加载视频数据:浏览器开始加载视频文件,并将数据传输到客户端。
解码视频数据:一旦足够的视频数据被下载,浏览器会对视频数据进行解码,以便能够播放视频。
渲染视频帧:解码后的视频数据将被渲染为一系列连续的视频帧。浏览器会将这些视频帧显示在屏幕上,实现视频的播放效果。
<video autoplay></video>
需要注意的是,浏览器对autoplay属性有一些限制和要求。根据浏览器的策略,autoplay只会在以下情况下生效:
视频必须是静音的:出于用户体验和防止滥用的考虑,大多数浏览器要求自动播放的视频必须是静音的。如果视频带有声音,浏览器将忽略autoplay属性,需要用户主动点击播放按钮才能启动声音。
用户曾与网站有过交互:为了避免滥用和不受用户控制的自动播放,大多数浏览器要求用户在过去与网站进行过有效的交互(例如点击、触摸等),才能启用autoplay属性。这样可以确保用户有意愿并且已经与网站进行了互动,才能进行自动播放。
这种播放策略主要是出于对用户隐私安全考虑。
播放/暂停按钮:用于控制视频的播放和暂停。
进度条:显示视频的当前播放进度,并允许用户拖动到指定位置进行跳转。
音量控制:用于调整视频的音量大小。
全屏切换按钮:用于将视频切换到全屏模式或恢复到正常模式。
<video controls></video>
<video loop></video>
<video muted></video>
<video preload="auto"></video>
<video poster="poster.jpg"></video>
效果图:
想要好看的gif动态加载图素材这里推荐几个UI网站
<video width="640" height="360"></video>
- <template>
- <div class="app-container">
- <video ref="video" :src="videoSrc" controls width="640" height="360" :autoplay="true" loop muted :poster="posterSrc"
- preload="auto" @loadeddata="handleLoadedData" @loadedmetadata="handleLoadedMetadata" @canplay="handleCanPlay"
- @canplaythrough="handleCanPlayThrough" @play="handlePlay" @pause="handlePause" @ended="handleEnded"
- @timeupdate="handleTimeUpdate" @seeked="handleSeeked" @volumechange="handleVolumeChange"></video>
- </div>
- </template>
-
- <script>
- export default {
- data() {
- return {
- videoSrc: require('@/assets/video/《持续发力 纵深推进》.mp4'),
- posterSrc: require('@/assets/images/loading4.gif'),
- currentTime: 0,
- duration: 0,
- }
- },
-
- mounted() {
- this.$refs.video.addEventListener('loadedmetadata', this.handleLoadedMetadata);
- this.$refs.video.addEventListener('timeupdate', this.handleTimeUpdate);
- },
-
- methods: {
- handleLoadedData() {
- console.log('视频第一帧已加载完成');
- },
- handleLoadedMetadata() {
- console.log('视频元数据已加载完成');
- this.duration = this.$refs.video.duration;
- },
- handleCanPlay() {
- console.log('视频可以开始播放');
- },
- handleCanPlayThrough() {
- console.log('视频可以完整地播放');
- },
- handlePlay() {
- console.log('视频开始播放');
- },
- handlePause() {
- console.log('视频暂停');
- },
- handleEnded() {
- console.log('视频播放结束');
- },
- handleTimeUpdate() {
- console.log('视频播放时间发生变化');
- this.currentTime = this.$refs.video.currentTime;
- },
- handleSeeked() {
- console.log('用户完成跳转');
- },
- handleVolumeChange() {
- console.log('音量发生变化');
- },
-
-
- }
- }
- </script>
1、@loadedmetadata:在元数据加载后触发,元数据包括视频的长度、尺寸等信息。
2、@loadeddata:在视频的第一帧加载完成后触发,即视频首次可播放。
3、@canplay:在视频可以开始播放时触发。
4、@canplaythrough:在视频缓冲完毕并且可以流畅播放时触发。
5、@play:在视频播放时触发
6、@timeupdate:在视频播放位置发生改变时触发,例如快进、倒带或者正常播放。
7、@seeked:在视频跳转到新的播放位置时触发,例如拖动进度条。
8、@pause:在视频暂停时触发。
9、@ended:在视频播放完毕时触发。
10、@volumechange:在音量发生改变时触发。
注意:这些事件可能不是按照这个顺序依次发生的,有些事件可能会在其他事件之前或之后发生。
直接上效果图+代码吧:样式比较简陋,这里只做演示
- <template>
- <div class="app-container">
- <video ref="video" class="video" :src="videoSrc" controls width="640" height="360" :autoplay="true" loop muted
- :poster="posterSrc" preload="auto" @loadeddata="handleLoadedData" @loadedmetadata="handleLoadedMetadata"
- @canplay="handleCanPlay" @canplaythrough="handleCanPlayThrough" @play="handlePlay" @pause="handlePause"
- @ended="handleEnded" @timeupdate="handleTimeUpdate" @seeked="handleSeeked"
- @volumechange="handleVolumeChange"></video>
- <div class="video-info">
- <p>总时长: {{ duration }} S</p>
- <p>当前播放时长: {{ currentTime }} S</p>
- <p>播放进度: {{ progress }} %</p>
- <p>当前音量: {{ volume }} </p>
- </div>
- </div>
- </template>
-
- <script>
- export default {
- data() {
- return {
- videoSrc: require('@/assets/video/《持续发力 纵深推进》.mp4'),
- posterSrc: require('@/assets/images/loading4.gif'),
- duration: 0, // 视频总时长
- currentTime: 0, // 当前播放时长
- progress: 0,// 播放进度
- volume: 1,//当前音量
- }
- },
-
- mounted() {
- // 获取video元素
- const videoElement = this.$refs.video;
-
- // 监听loadedmetadata事件,在元数据加载后获取视频总时长
- videoElement.addEventListener('loadedmetadata', () => {
- this.duration = Number(videoElement.duration).toFixed(0);
- });
-
- },
-
- methods: {
- handleLoadedData() {
- console.log('视频第一帧已加载完成');
- },
- handleLoadedMetadata() {
- console.log('视频元数据已加载完成');
- this.duration = Number(this.$refs.video.duration).toFixed(0);
- },
- handleCanPlay() {
- console.log('视频可以开始播放');
- },
- handleCanPlayThrough() {
- console.log('视频可以完整地播放');
- },
- handlePlay() {
- console.log('视频开始播放');
- },
- handlePause() {
- console.log('视频暂停');
- },
- handleEnded() {
- console.log('视频播放结束');
- },
- handleTimeUpdate() {
- console.log('视频播放时间发生变化');
- // 更新当前播放时长
- this.currentTime = Number(this.$refs.video.currentTime).toFixed(0);
-
- // 更新播放进度
- this.progress = Number((this.currentTime / this.duration) * 100).toFixed(2);
- },
- handleSeeked() {
- console.log('用户完成跳转');
- },
- handleVolumeChange() {
- console.log('音量发生变化');
- // 更新音量状态
- this.volume = parseInt(Number(this.$refs.video.volume) * 100);
- },
-
-
- }
- }
- </script>
-
- <style lang="scss" scoped>
- .app-container {
- width: 100%;
- height: 100%;
- display: flex;
-
- .video {}
-
- .video-info {
- border: 1px solid #EE6F7C;
- height: 360px;
- width: 300px;
- display: flex;
- flex-direction: column;
- justify-content: flex-start;
- align-items: flex-start;
- padding-left: 20px;
- }
- }
- </style>
以上是一些基本的视频事件用法,具体需要根据需求定制化开发。
准备弹幕数据:首先需要准备好弹幕的数据,包括每条弹幕的内容、显示时间、位置等信息。可以将这些数据存储在一个数组或者从后端获取。
创建弹幕容器:在视频播放页面中创建一个用于显示弹幕的容器,可以是一个
<div>
元素或者其他适合的 HTML 元素。这个容器将用于承载弹幕元素,并设置相应的样式和位置。动态创建弹幕元素:根据弹幕数据,使用 JavaScript 动态创建弹幕元素,并将其添加到弹幕容器中。可以使用 DOM 操作或者框架提供的方法来实现。
控制弹幕显示:根据视频的播放时间,控制弹幕的显示和隐藏。可以使用定时器或者事件监听来实现。根据弹幕的显示时间和视频播放进度,决定哪些弹幕需要显示在当前时间段内。
弹幕样式和动画:为弹幕元素设置合适的样式,包括字体、颜色、大小等。可以使用 CSS 来控制弹幕的样式,并通过 CSS 动画或者 JavaScript 动画来实现弹幕的滚动效果。
用户交互:如果需要支持用户发送和显示实时弹幕,可以提供相应的输入框和发送按钮,并将用户输入的弹幕实时添加到弹幕容器中。
- <template>
- <div class="app-container">
- <div class="danmu-container">
- <video ref="video" class="video" :src="videoSrc" controls width="640" height="360" :autoplay="true" loop muted
- :poster="posterSrc" preload="auto" @loadeddata="handleLoadedData" @loadedmetadata="handleLoadedMetadata"
- @canplay="handleCanPlay" @canplaythrough="handleCanPlayThrough" @play="handlePlay" @pause="handlePause"
- @ended="handleEnded" @timeupdate="handleTimeUpdate" @seeked="handleSeeked"
- @volumechange="handleVolumeChange">
- </video>
- <div class="danmu" v-for="danmu in danmuList"
- :style="{ color: danmu.color, top: danmu.top + 'px', left: danmu.left + 'px', fontSize: danmu.fontSize + 'px' }"
- :class="{ animated: true }" style="animation-duration: 8s; animation-timing-function: linear;">
- {{ danmu.text }}
- </div>
- </div>
- <div class="video-info">
- <p>总时长: {{ duration }} S</p>
- <p>当前播放时长: {{ currentTime }} S</p>
- <p>播放进度: {{ progress }} %</p>
- <p>当前音量: {{ volume }} </p>
- <!-- 弹幕输入框和发送按钮 -->
- <div class="danmu-input">
- <input type="text" placeholder="请输入弹幕..." v-model="danmuText">
- <button @click="sendDanmu">发送</button>
- </div>
- </div>
- </div>
- </template>
- methods: {
- // 发送弹幕
- sendDanmu() {
- // 构造一个弹幕对象
- const danmu = {
- text: this.danmuText,
- color: '#' + Math.floor(Math.random() * 0xffffff).toString(16), // 随机颜色
- fontSize: Math.floor(Math.random() * 20 + 16), // 随机字号
- top: Math.floor(Math.random() * 280 + 40), // 随机高度
- left: 640 // 初始位置在右侧界面外
- }
- // 将弹幕添加到弹幕列表中
- this.danmuList.push(danmu)
- // 清空弹幕输入框
- this.danmuText = ''
- },
- // 滚动弹幕
- scrollDanmu() {
- const container = document.querySelector('.danmu-container')
- const danmus = container.querySelectorAll('.danmu')
- danmus.forEach(danmu => {
- const left = parseInt(danmu.style.left)
- if (left < -danmu.offsetWidth) {
- // 弹幕已经滚动到左侧界面外,需要移除
- container.removeChild(danmu)
- } else {
- // 弹幕还在屏幕内,继续滚动
- danmu.style.left = left - 2 + 'px'
- }
- })
- },
- // 视频播放时,每隔一段时间滚动弹幕
- handleTimeUpdate() {
- this.scrollDanmu()
- },
-
- handleTimeUpdate() {
- console.log('视频播放时间发生变化');
- // 更新当前播放时长
- this.currentTime = Number(this.$refs.video.currentTime).toFixed(0);
- // 更新播放进度
- this.progress = Number((this.currentTime / this.duration) * 100).toFixed(2);
- this.scrollDanmu()
- },
- }
-
- <style lang="scss" scoped>
- .app-container {
- width: 100%;
- height: 100%;
- display: flex;
-
- .video {}
-
- .video-info {
- border: 1px solid #EE6F7C;
- height: 360px;
- width: 300px;
- display: flex;
- flex-direction: column;
- justify-content: flex-start;
- align-items: flex-start;
- padding-left: 20px;
- }
-
- /* 弹幕容器样式 */
- .danmu-container {
- position: relative;
- width: 640px;
- height: 360px;
- overflow: hidden;
- }
-
- /* 弹幕样式 */
- .danmu {
- position: absolute;
- white-space: nowrap;
- }
- }
-
- .danmu.animated {
- animation-name: scroll;
- transform: translateZ(0);
- }
-
-
- @keyframes scroll {
- from {
- transform: translateX(100%);
- }
-
- to {
- transform: translateX(-100%);
- }
- }
- </style>
controls
属性启用浏览器原生的控制条,并使用CSS样式对其进行美化和定制。Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。