普通视图

发现新文章,点击刷新页面。
今天 — 2025年11月24日掘金 前端

栗子前端技术周刊第 107 期 - Angular v21、pnpm 10.22、React 2025 现状调查...

2025年11月24日 09:00

🌰栗子前端技术周刊第 107 期 (2025.11.17 - 2025.11.23):浏览前端一周最新消息,学习国内外优秀文章视频,让我们保持对前端的好奇心。

📰 技术资讯

  1. Angular v21:谷歌发布 Angular v21 版本,本次更新不仅打造了一场复古游戏主题的探索之旅,用于展示新版本的各项新特性,还推出了一系列高质量视频,集中演示了以下功能:基于信号(signal-based)的表单处理新方案、支持 AI 驱动工作流的 MCP 服务器、专注于可访问性(无障碍性)的无头组件库,甚至还新增了一款“Angular AI 导师”工具,助力开发者快速上手新版本。

  2. pnpm 10.22: pnpm 10.22 发布,该版本新增 trustPolicyExclude 配置项,可用于指定“即便存在其他信任策略要求,仍需安装”的包。

  3. React 2025 现状调查:React 2025 现状调查现已开启,问卷提交将于 11 月 25 日截止,有兴趣的可以参加。

📒 技术文章

  1. Six Things I Bet You Didn't Know You Could Do With Chrome's Devtools, Part 1:你可能不知道的 Chrome 开发者工具六大用法(第一部分)- 本篇文章将介绍使用 console.time ()console.timeEnd () 的计时功能、监听任意 DOM 元素的变化和监控浏览器上下文环境中的任意函数,其他部分将在下篇文章介绍。

  2. Cursor 一年深度开发实践:前端开发的效率革命:本文作者分享了使用 Cursor 进行前端开发的实践经验,展示了移动端、PC 端多个项目中 Cursor 的高效应用,还验证了其工程化处理能力。

  3. 转转 UI 自动化走查方案探索:文章围绕转转 UI 自动化走查方案展开,先指出当前 UI 走查存在效率低、还原度难控等问题。后经调研,选择基于前端与 UI 节点的比对方案,介绍了数据结构设计、归一化处理流程,包括处理行高、边距合并等问题。

🔧 开发工具

  1. Webpack Bundle Analyzer 5.0:可视化查看 Webpack 输出内容。
image-20251123131443566
  1. Marked.js 17.0:快速的 Markdown 解析器与编译器,Marked.js 可作为客户端库、服务器端库使用,甚至还支持命令行界面(CLI)。
image-20251123131824469
  1. is-online 12.0:该工具可在 Node.js 环境与浏览器环境中运行,并通过多种方式判断互联网是否真正处于可用状态。
image-20251123132105379

🚀🚀🚀 以上资讯文章选自常见周刊,如 JavaScript Weekly 等,周刊内容也会不断优化改进,希望你们能够喜欢。

💖 欢迎关注微信公众号:栗子前端

HTML的Video从基础使用到高级实战+兼容的完全指南

作者 鹏多多
2025年11月24日 08:59

HTML5 的 <video> 标签彻底改变了网页视频播放的实现方式——无需依赖 Flash 等第三方插件,原生支持跨平台视频播放,兼具轻量性与扩展性。本文将从标签基础、API 详解、事件体系、样式控制、兼容性处理等维度,全面解析 <video> 标签的技术细节与实战技巧。

1. 核心用法与属性

下面是标签的核心用法与属性:

1.1. 基本语法结构

<video> 标签的核心作用是嵌入视频资源,最简用法如下:

<!-- 基础用法:指定视频源与基础控制 -->
<video src="video.mp4" controls width="640" height="360">
  <!-- 降级提示:浏览器不支持 video 标签时显示 -->
  您的浏览器不支持 HTML5 视频播放,请升级浏览器或更换观看方式。
</video>

1.2. 核心属性详解

属性名 取值 功能说明
src 视频文件 URL 指定单个视频源(优先推荐使用 <source> 标签适配多格式)
controls 布尔值(省略则生效) 显示浏览器原生控制栏(播放/暂停、音量、进度条等)
autoplay 布尔值 页面加载完成后自动播放(注意:多数浏览器要求静音才能自动播放)
muted 布尔值 视频默认静音
loop 布尔值 视频播放完毕后自动循环
preload auto/metadata/none 预加载策略:
- auto:自动预加载整个视频(默认)
- metadata:仅预加载元数据(时长、尺寸等)
- none:不预加载任何内容
poster 图片 URL 视频加载完成前/未播放时显示的封面图
width/height 像素值(如 640 视频播放器的宽高(建议通过 CSS 控制,更灵活)
playsinline 布尔值 允许视频在页面内播放(而非全屏,移动端必备)
webkit-playsinline 布尔值 iOS Safari 兼容属性(与 playsinline 配合使用)

1.3. 多格式适配: 标签

不同浏览器对视频格式支持存在差异(如 MP4 兼容所有现代浏览器,WebM 体积更小但兼容性较差),需通过 <source> 标签提供多格式备选:

<video controls poster="cover.jpg" playsinline webkit-playsinline>
  <!-- 浏览器会按顺序选择支持的格式 -->
  <source src="video.mp4" type="video/mp4">
  <source src="video.webm" type="video/webm">
  <source src="video.ogg" type="video/ogg">
  您的浏览器不支持 HTML5 视频播放,请升级浏览器。
</video>

推荐格式组合:MP4(主格式)+ WebM(备选),覆盖 99% 以上现代浏览器。

2. 核心 API:通过JavaScript控制

<video> 元素暴露了丰富的 JavaScript API,可实现自定义播放逻辑、状态查询等功能。获取视频元素后即可调用:

const video = document.querySelector('video'); // 获取视频元素

2.1. 核心方法

方法名 功能说明
play() 开始播放视频,返回 Promise(需处理播放失败场景)
pause() 暂停播放视频
load() 重新加载视频资源(常用于切换视频源后)
canPlayType(type) 检测浏览器是否支持指定视频格式(返回 probably/maybe/""
requestFullscreen() 进入全屏模式(需兼容前缀:webkitRequestFullscreen 等)

2.2. 关键属性(可读写/只读)

(1)可读写属性(控制视频行为)

属性名 类型 说明
currentTime Number 当前播放位置(秒),可设置跳转
volume Number 音量(0~1,0 为静音,1 为最大音量)
playbackRate Number 播放速率(1 为正常,0.5 为慢放,2 为快放)
muted Boolean 设置是否静音(与标签属性一致)
loop Boolean 设置是否循环(与标签属性一致)

(2)只读属性(获取视频状态)

属性名 类型 说明
duration Number 视频总时长(秒),未加载完成时为 NaN
paused Boolean 是否处于暂停状态(true 为暂停)
playing Boolean 是否正在播放(H5 新增,需兼容)
buffered TimeRanges 已缓冲的时间范围(通过 buffered.start(0)/buffered.end(0) 获取)
readyState Number 视频就绪状态:
0 = 未就绪
1 = 元数据就绪
2 = 当前帧就绪
3 = 可播放(已缓冲部分内容)
4 = 完全就绪
networkState Number 网络状态:
0 = 未初始化
1 = 正在加载
2 = 加载完成
3 = 加载失败

2.3. API 实战示例

const video = document.querySelector('video');

// 1. 播放/暂停切换
document.getElementById('playBtn').addEventListener('click', () => {
  if (video.paused) {
    // 处理自动播放限制(需静音或用户交互后)
    video.play().catch(err => {
      console.log('播放失败:', err);
      video.muted = true;
      video.play(); // 静音后重试自动播放
    });
  } else {
    video.pause();
  }
});

// 2. 跳转至指定时间(如 30 秒)
document.getElementById('jumpBtn').addEventListener('click', () => {
  video.currentTime = 30;
});

// 3. 调整音量(50%)
video.volume = 0.5;

// 4. 快放(1.5 倍速)
video.playbackRate = 1.5;

// 5. 检测格式支持
console.log('MP4 支持:', video.canPlayType('video/mp4') !== '');
console.log('WebM 支持:', video.canPlayType('video/webm') !== '');

3. 监听视频生命周期与状态变化事件

<video> 标签提供了完整的事件机制,可监听播放状态、加载进度、错误等场景,是实现自定义控制逻辑的核心。

3.1. 核心事件分类与说明

事件名 触发时机 应用场景
loadedmetadata 视频元数据(时长、尺寸等)加载完成 获取视频总时长 duration
loadeddata 第一帧视频加载完成并可显示 隐藏加载动画、显示视频画面
canplay 视频已缓冲足够数据,可开始播放(可能卡顿) 启用播放按钮
canplaythrough 视频已缓冲至末尾,可流畅播放 提示“可流畅观看”
play 调用 play() 后开始播放时 切换播放按钮状态(暂停图标)
pause 调用 pause() 或播放暂停时 切换播放按钮状态(播放图标)
timeupdate 播放位置 currentTime 变化时(约 250ms 一次) 更新进度条、显示当前播放时间
progress 视频缓冲时持续触发 更新缓冲进度条
ended 视频播放完毕时 显示“播放完成”提示、自动重播
error 视频加载/播放失败时 显示错误提示(通过 error.code 获取错误类型)
volumechange 音量/静音状态变化时 更新音量图标
fullscreenchange 全屏状态变化时 切换全屏/退出全屏按钮

3.2. 事件监听实战示例

const video = document.querySelector('video');
const progressBar = document.querySelector('.progress-bar');
const currentTimeText = document.querySelector('.current-time');
const durationText = document.querySelector('.duration');

// 1. 元数据加载完成:显示总时长
video.addEventListener('loadedmetadata', () => {
  durationText.textContent = formatTime(video.duration);
});

// 2. 播放位置更新:同步进度条
video.addEventListener('timeupdate', () => {
  const progress = (video.currentTime / video.duration) * 100;
  progressBar.style.width = `${progress}%`;
  currentTimeText.textContent = formatTime(video.currentTime);
});

// 3. 缓冲进度更新:显示缓冲条
video.addEventListener('progress', () => {
  if (video.buffered.length > 0) {
    const bufferedEnd = video.buffered.end(video.buffered.length - 1);
    const bufferedProgress = (bufferedEnd / video.duration) * 100;
    document.querySelector('.buffer-bar').style.width = `${bufferedProgress}%`;
  }
});

// 4. 播放完成:提示并重置
video.addEventListener('ended', () => {
  alert('视频播放完成!');
  video.currentTime = 0; // 重置播放位置
});

// 5. 错误处理:显示错误信息
video.addEventListener('error', () => {
  switch(video.error.code) {
    case 1: alert('视频加载中断'); break;
    case 2: alert('不支持的视频格式'); break;
    case 3: alert('视频解码失败'); break;
    case 4: alert('视频加载超时'); break;
  }
});

// 辅助函数:格式化时间(秒 → 分:秒,如 125 → 2:05)
function formatTime(seconds) {
  if (isNaN(seconds)) return '0:00';
  const min = Math.floor(seconds / 60);
  const sec = Math.floor(seconds % 60);
  return `${min}:${sec.toString().padStart(2, '0')}`;
}

4. 自定义播放器外观样式

浏览器原生控制栏样式难以适配不同网页设计,通过隐藏原生 controls,使用 CSS 自定义播放器界面是更常用的方案。

4.1. 基础样式控制

/* 1. 视频容器样式(统一尺寸、边框、圆角) */
.video-container {
  position: relative;
  width: 100%;
  max-width: 1280px;
  margin: 0 auto;
  border-radius: 8px;
  overflow: hidden;
  box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}

/* 2. 视频元素样式(填充容器,避免变形) */
.video-container video {
  width: 100%;
  height: auto;
  object-fit: cover; /* 保持宽高比,填充容器(可能裁剪边缘) */
  background: #000; /* 未加载时显示黑色背景 */
}

/* 3. 封面图样式(与视频同尺寸) */
.video-container poster {
  object-fit: cover;
}

4.2. 自定义控制栏样式

通过绝对定位在视频底部创建自定义控制栏,默认隐藏,鼠标悬浮时显示:

/* 控制栏容器 */
.video-controls {
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  padding: 10px;
  background: linear-gradient(transparent, rgba(0,0,0,0.7)); /* 渐变背景 */
  color: #fff;
  opacity: 0;
  transition: opacity 0.3s ease;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

/* 鼠标悬浮时显示控制栏 */
.video-container:hover .video-controls {
  opacity: 1;
}

/* 进度条容器 */
.progress-container {
  height: 4px;
  background: rgba(255,255,255,0.3);
  border-radius: 2px;
  cursor: pointer;
}

/* 已播放进度条 */
.progress-bar {
  height: 100%;
  background: #ff4400;
  border-radius: 2px;
  width: 0%;
}

/* 缓冲进度条(叠加在进度条下方) */
.buffer-bar {
  height: 100%;
  background: rgba(255,255,255,0.5);
  border-radius: 2px;
  width: 0%;
  position: absolute;
  top: 0;
  left: 0;
  z-index: 1;
}

/* 控制按钮区域 */
.controls-buttons {
  display: flex;
  align-items: center;
  gap: 16px;
  font-size: 14px;
}

/* 按钮样式 */
.controls-btn {
  background: transparent;
  border: none;
  color: #fff;
  cursor: pointer;
  font-size: 16px;
  transition: color 0.2s;
}

.controls-btn:hover {
  color: #ff4400;
}

/* 音量控制滑块 */
.volume-slider {
  width: 60px;
  height: 4px;
  background: rgba(255,255,255,0.3);
  border-radius: 2px;
  outline: none;
  accent-color: #ff4400; /* 自定义滑块颜色 */
}

4.3. 自定义控制栏 HTML 结构

<div class="video-container">
  <video src="video.mp4" poster="cover.jpg" playsinline webkit-playsinline>
    您的浏览器不支持 HTML5 视频播放。
  </video>
  <!-- 自定义控制栏 -->
  <div class="video-controls">
    <div class="progress-container" id="progressContainer">
      <div class="buffer-bar"></div>
      <div class="progress-bar"></div>
    </div>
    <div class="controls-buttons">
      <button class="controls-btn" id="playBtn">▶️</button>
      <span class="current-time">0:00</span>
      <span>/</span>
      <span class="duration">0:00</span>
      <input type="range" class="volume-slider" id="volumeSlider" min="0" max="1" step="0.01" value="1">
      <button class="controls-btn" id="fullscreenBtn"></button>
    </div>
  </div>
</div>

5. 兼容性处理与常见问题

下面是一些兼容性处理与常见问题:

5.1. 浏览器兼容性

(1)核心兼容性现状

  • 现代浏览器:Chrome、Firefox、Safari、Edge 均完美支持 <video> 标签及核心 API。
  • 移动端:iOS Safari、Android Chrome 支持良好,但需注意 playsinline 属性(避免自动全屏)。
  • 旧浏览器:IE8 及以下不支持 <video> 标签,需通过降级提示或 Flash 备用方案(已不推荐)。

(2)格式兼容性

视频格式 支持浏览器 优势
MP4(H.264 + AAC) 所有现代浏览器、iOS、Android 兼容性最好,推荐主格式
WebM(VP8/VP9 + Vorbis) Chrome、Firefox、Edge 体积小、开源,备选格式
OGG(Theora + Vorbis) Chrome、Firefox 开源,兼容性较差(几乎不用)

(3)API 兼容性处理

部分 API 需添加浏览器前缀(如全屏、播放速率),示例如下:

// 全屏兼容处理
function toggleFullscreen(video) {
  if (document.fullscreenElement) {
    // 退出全屏
    document.exitFullscreen().catch(err => console.log(err));
  } else {
    // 进入全屏(兼容前缀)
    if (video.requestFullscreen) {
      video.requestFullscreen();
    } else if (video.webkitRequestFullscreen) { // Safari
      video.webkitRequestFullscreen();
    } else if (video.msRequestFullscreen) { // IE/Edge
      video.msRequestFullscreen();
    }
  }
}

// 播放速率兼容性(部分旧浏览器不支持)
function setPlaybackRate(video, rate) {
  if (typeof video.playbackRate !== 'undefined') {
    video.playbackRate = rate;
  } else {
    alert('您的浏览器不支持播放速率调整');
  }
}

5.2. 常见问题与解决方案

(1)自动播放失败

  • 原因:现代浏览器限制“非静音自动播放”(需用户交互后才能播放有声视频)。
  • 解决方案
    1. 默认静音自动播放(muted autoplay),提供“开启声音”按钮。
    2. 引导用户点击后播放(如“点击播放”封面图)。
    <video src="video.mp4" autoplay muted playsinline>...</video>
    

(2)视频加载缓慢/卡顿

  • 解决方案
    1. 提供多码率视频(根据网络状况切换)。
    2. 使用 preload="metadata" 优化预加载策略。
    3. 显示缓冲进度条,提示用户“缓冲中”。
    4. 采用 CDN 分发视频资源,提升加载速度。

(3)视频比例变形

  • 原因:播放器宽高与视频原生宽高比不一致。
  • 解决方案:使用 object-fit 属性控制视频填充方式:
    video {
      object-fit: cover; /* 保持宽高比,填充容器(裁剪边缘) */
      /* 或 object-fit: contain; 保持宽高比,完整显示(可能留黑边) */
    }
    

(4)移动端自动全屏播放

  • 原因:iOS Safari 默认会将视频全屏播放(无 playsinline 属性时)。
  • 解决方案:添加 playsinlinewebkit-playsinline 属性:
    <video src="video.mp4" playsinline webkit-playsinline>...</video>
    

6. 总结

HTML5 <video> 标签凭借原生、轻量、可扩展的特性,成为网页视频播放的标准方案。通过本文的讲解,你可以掌握:

  1. 标签基础属性与多格式适配技巧;
  2. 核心 API 的使用的(播放控制、状态查询);
  3. 完整事件体系的应用(监听播放状态、缓冲进度等);
  4. 自定义播放器的样式设计与逻辑实现;
  5. 兼容性处理与常见问题解决方案。

在实际开发中,可根据需求灵活组合上述技术——简单场景直接使用原生控制栏,复杂场景(如视频网站、教育平台)则通过自定义控制栏与 API 实现个性化功能(如倍速播放、弹幕、画中画等)。随着浏览器技术的迭代,<video> 标签的功能将持续完善,为网页视频体验带来更多可能。


本次分享就到这儿啦,我是鹏多多,深耕前端的技术创作者,如果您看了觉得有帮助,欢迎评论,关注,点赞,转发,我们下次见~

PS:在本页按F12,在console中输入document.getElementsByClassName('panel-btn')[0].click();有惊喜哦~

往期文章

❌
❌