Skip to content

HTML5 多媒体与绘图面试题全解析

一、核心要点速览

💡 核心考点

  • audio/video: 原生音视频播放及控制
  • Canvas: 2D 绘图 API 及应用场景
  • SVG: 矢量图形与 Canvas 对比
  • 媒体事件: 加载、播放、暂停等事件处理

二、音视频标签详解

1. audio 标签使用

html
<!-- 基础用法 -->
<audio controls autoplay loop preload="metadata">
  <source src="audio.mp3" type="audio/mpeg">
  <source src="audio.ogg" type="audio/ogg">
  您的浏览器不支持 audio 标签
</audio>

<!-- 重要属性 -->
<audio 
  controls        <!-- 显示控制条 -->
  autoplay        <!-- 自动播放(可能被浏览器阻止)-->
  loop           <!-- 循环播放 -->
  muted          <!-- 静音 -->
  preload="auto" <!-- 预加载:none|metadata|auto -->
>
  <source src="audio.mp3" type="audio/mpeg">
  <track 
    kind="captions" 
    src="captions.vtt" 
    srclang="zh" 
    label="中文字幕"
  >
</audio>

2. video 标签使用

html
<video 
  width="640" 
  height="480" 
  controls 
  poster="cover.jpg"
  preload="metadata"
  muted
  playsinline     <!-- iOS 禁止自动全屏 -->
  webkit-playsinline
>
  <source src="video.mp4" type="video/mp4">
  <source src="video.webm" type="video/webm">
  
  <!-- 多分辨率适配 -->
  <source src="video-720p.mp4" type="video/mp4" media="(min-width: 1200px)">
  <source src="video-480p.mp4" type="video/mp4" media="(min-width: 768px)">
  <source src="video-360p.mp4" type="video/mp4">
  
  <!-- 字幕 -->
  <track 
    kind="subtitles" 
    src="subs.vtt" 
    srclang="zh" 
    label="中文"
    default
  >
  
  您的浏览器不支持 video 标签
</video>

3. JavaScript 控制媒体

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

// 播放控制
video.play()              // 播放
video.pause()             // 暂停
video.currentTime = 100   // 跳转到 100 秒

// 属性设置
video.volume = 0.5        // 音量 50%
video.playbackRate = 1.5  // 1.5 倍速
video.muted = true        // 静音
video.loop = true         // 循环

// 获取信息
console.log(video.duration)    // 总时长(秒)
console.log(video.currentTime) // 当前时间
console.log(video.paused)      // 是否暂停
console.log(video.ended)       // 是否结束

// 监听事件
video.addEventListener('play', () => {
  console.log('开始播放')
})

video.addEventListener('pause', () => {
  console.log('暂停播放')
})

video.addEventListener('timeupdate', () => {
  const percent = (video.currentTime / video.duration) * 100
  console.log(`播放进度:${percent.toFixed(2)}%`)
})

video.addEventListener('ended', () => {
  console.log('播放完成')
})

video.addEventListener('waiting', () => {
  console.log('缓冲中...')
})

video.addEventListener('canplay', () => {
  console.log('可以播放了')
})

4. 媒体事件时序图

时间 →  ─────────────────────────────────────────────────►

视频加载播放流程:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
┌─────────┐
│ 加载视频 │
└────┬────┘


┌─────────────┐
│ loadstart   │ ← 开始加载
└──────┬──────┘


┌─────────────┐
│ durationchange│ ← 获取到时长
└──────┬──────┘


┌─────────────┐
│ loadeddata  │ ← 当前帧可用
└──────┬──────┘


┌─────────────┐
│ loadedmetadata│ ← 元数据加载完成
└──────┬──────┘


┌─────────────┐
│ canplay     │ ← 可以开始播放
└──────┬──────┘


┌─────────────┐
│ play()      │ ← 开始播放
└──────┬──────┘


┌─────────────┐
│ timeupdate  │ ← 持续触发 (每 250ms)
└──────┬──────┘


┌─────────────┐
│ ended       │ ← 播放结束
└─────────────┘

常用事件说明:
✓ loadstart: 加载开始
✓ progress: 加载进度
✓ durationchange: 时长变化
✓ loadeddata: 当前帧数据就绪
✓ loadedmetadata: 元数据就绪
✓ canplay: 可以播放
✓ playing: 正在播放
✓ pause: 暂停
✓ timeupdate: 时间更新
✓ ended: 播放结束
✓ error: 加载错误
✓ waiting: 缓冲等待
✓ seeking: 跳转中
✓ seeked: 跳转完成
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

三、Canvas 绘图详解

1. Canvas 基础

html
<canvas id="myCanvas" width="800" height="600"></canvas>
javascript
const canvas = document.getElementById('myCanvas')
const ctx = canvas.getContext('2d')

// 1. 绘制矩形
ctx.fillStyle = '#FF0000'
ctx.fillRect(10, 10, 100, 100)  // 填充矩形

ctx.strokeStyle = '#000000'
ctx.lineWidth = 2
ctx.strokeRect(120, 10, 100, 100)  // 描边矩形

ctx.clearRect(230, 10, 100, 100)  // 清除矩形

// 2. 绘制路径
ctx.beginPath()  // 开始路径
ctx.moveTo(50, 200)  // 移动到起点
ctx.lineTo(150, 200)  // 画线
ctx.lineTo(100, 300)  // 画线
ctx.closePath()  // 闭合路径

ctx.fillStyle = 'blue'
ctx.fill()  // 填充

ctx.strokeStyle = 'black'
ctx.stroke()  // 描边

// 3. 绘制圆形
ctx.beginPath()
ctx.arc(300, 200, 50, 0, Math.PI * 2)  // 圆心、半径、起始角、结束角
ctx.fillStyle = 'green'
ctx.fill()

// 4. 绘制文字
ctx.font = '30px Arial'
ctx.fillStyle = 'black'
ctx.fillText('Hello Canvas', 50, 400)  // 填充文字
ctx.strokeText('Hello Canvas', 50, 450)  // 描边文字

// 5. 绘制渐变
const gradient = ctx.createLinearGradient(100, 500, 300, 500)
gradient.addColorStop(0, 'red')
gradient.addColorStop(1, 'blue')

ctx.fillStyle = gradient
ctx.fillRect(100, 500, 200, 50)

2. 完整绘图示例

javascript
const canvas = document.getElementById('canvas')
const ctx = canvas.getContext('2d')

// 绘制一个笑脸
function drawSmiley(x, y, radius) {
  // 1. 脸部
  ctx.beginPath()
  ctx.arc(x, y, radius, 0, Math.PI * 2)
  ctx.fillStyle = '#FFD700'
  ctx.fill()
  ctx.strokeStyle = '#000'
  ctx.lineWidth = 2
  ctx.stroke()
  
  // 2. 左眼
  ctx.beginPath()
  ctx.arc(x - radius/3, y - radius/5, radius/10, 0, Math.PI * 2)
  ctx.fillStyle = '#000'
  ctx.fill()
  
  // 3. 右眼
  ctx.beginPath()
  ctx.arc(x + radius/3, y - radius/5, radius/10, 0, Math.PI * 2)
  ctx.fillStyle = '#000'
  ctx.fill()
  
  // 4. 嘴巴
  ctx.beginPath()
  ctx.arc(x, y, radius/2, 0.2 * Math.PI, 0.8 * Math.PI)
  ctx.strokeStyle = '#000'
  ctx.lineWidth = 3
  ctx.stroke()
}

drawSmiley(200, 200, 100)

3. Canvas 动画示例

javascript
const canvas = document.getElementById('canvas')
const ctx = canvas.getContext('2d')

let ball = {
  x: 50,
  y: 50,
  vx: 2,  // x 方向速度
  vy: 2,  // y 方向速度
  radius: 20,
  color: 'red'
}

function animate() {
  // 清空画布
  ctx.clearRect(0, 0, canvas.width, canvas.height)
  
  // 更新位置
  ball.x += ball.vx
  ball.y += ball.vy
  
  // 边界检测
  if (ball.x + ball.radius > canvas.width || ball.x - ball.radius < 0) {
    ball.vx = -ball.vx
  }
  if (ball.y + ball.radius > canvas.height || ball.y - ball.radius < 0) {
    ball.vy = -ball.vy
  }
  
  // 绘制球
  ctx.beginPath()
  ctx.arc(ball.x, ball.y, ball.radius, 0, Math.PI * 2)
  ctx.fillStyle = ball.color
  ctx.fill()
  
  // 下一帧
  requestAnimationFrame(animate)
}

// 开始动画
animate()

四、Canvas vs SVG

1. 详细对比表

特性CanvasSVG
渲染方式像素(位图)矢量(XML)
缩放会失真不失真
性能大量对象高少量对象高
DOM 支持完整支持
事件绑定需手动实现原生支持
分辨率依赖
文件大小大(复杂图形)
学习曲线陡峭平缓
适用场景游戏、图表、图像处理图标、地图、数据可视化

2. 选择决策树

需要绘制什么?

    ├─ 高性能动画/游戏?
    │   └─ Canvas ✓
    │       └─ 例:粒子效果、俄罗斯方块

    ├─ 需要交互和事件?
    │   └─ SVG ✓
    │       └─ 例:可点击的图表、地图

    ├─ 需要无限缩放?
    │   └─ SVG ✓
    │       └─ 例:响应式图标、Logo

    ├─ 处理图像/像素?
    │   └─ Canvas ✓
    │       └─ 例:图片滤镜、截图工具

    └─ 简单静态图形?
        └─ SVG ✓(更简单)
            └─ 例:图标、简单图表

3. 代码对比

javascript
// Canvas 绘制矩形
const canvas = document.getElementById('canvas')
const ctx = canvas.getContext('2d')
ctx.fillStyle = 'red'
ctx.fillRect(10, 10, 100, 100)

// 修改矩形?需要重绘整个画布
ctx.clearRect(0, 0, canvas.width, canvas.height)
ctx.fillStyle = 'blue'
ctx.fillRect(10, 10, 100, 100)

// SVG 绘制矩形
const svg = `
  <svg width="200" height="200">
    <rect id="myRect" x="10" y="10" width="100" height="100" fill="red" />
  </svg>
`

// 修改矩形?直接操作 DOM
const rect = document.getElementById('myRect')
rect.setAttribute('fill', 'blue')
rect.setAttribute('width', '150')

// 添加事件
rect.addEventListener('click', () => {
  alert('点击了矩形!')
})

五、实际应用场景

1. Canvas 应用

┌──────────────────────────────────────────────────────────┐
│                  Canvas 应用场景                          │
└──────────────────────────────────────────────────────────┘

✓ 游戏开发
  ┌──────────────────────────────┐
  │ 俄罗斯方块、贪吃蛇等 2D 游戏   │
  │ 粒子系统、特效动画           │
  │ 高性能要求(60fps)          │
  └──────────────────────────────┘

✓ 数据可视化
  ┌──────────────────────────────┐
  │ ECharts、Chart.js 等图表库   │
  │ 实时数据展示                 │
  │ 大量数据点渲染               │
  └──────────────────────────────┘

✓ 图像处理
  ┌──────────────────────────────┐
  │ 图片滤镜、裁剪、压缩         │
  │ 截图工具                     │
  │ 图片水印                     │
  └──────────────────────────────┘

✓ 创意效果
  ┌──────────────────────────────┐
  │ 粒子背景、动态效果           │
  │ 签名板、画板应用             │
  └──────────────────────────────┘
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

2. SVG 应用

┌──────────────────────────────────────────────────────────┐
│                   SVG 应用场景                            │
└──────────────────────────────────────────────────────────┘

✓ 图标系统
  ┌──────────────────────────────┐
  │ 网站 Logo、功能图标          │
  │ 响应式设计(任意缩放)       │
  │ CSS 动画结合                 │
  └──────────────────────────────┘

✓ 数据可视化
  ┌──────────────────────────────┐
  │ D3.js 图表                   │
  │ 交互式图表(点击、悬停)     │
  │ 地图可视化                   │
  └──────────────────────────────┘

✓ UI 组件
  ┌──────────────────────────────┐
  │ 进度条、滑块                 │
  │ 图表仪表盘                   │
  │ 动态图形界面                 │
  └──────────────────────────────┘
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

六、面试标准回答

HTML5 提供了强大的多媒体和绘图能力

音视频方面,通过 audio 和 video 标签,我们可以原生播放音视频,无需 Flash 等第三方插件。支持多种格式、字幕、预加载等功能。JavaScript 可以完全控制播放、暂停、跳转等操作,并能监听各种事件来自定义播放器。

Canvas 是一个 2D 绘图 API,基于像素渲染。它适用于游戏、数据可视化、图像处理等场景。优点是性能好,适合大量对象的动态场景;缺点是不支持缩放,事件绑定复杂。

SVG 是基于 XML 的矢量图形,每个图形都是 DOM 元素。优点是可以无限缩放而不失真,支持事件绑定和 CSS 样式;缺点是复杂图形性能不如 Canvas。

选择上:如果需要高性能动画或处理像素,用 Canvas;如果需要交互、缩放或简单图形,用 SVG。实际项目中,像 ECharts 这样的库会根据场景混合使用两者。


七、记忆口诀

多媒体绘图歌诀:

audio video 播媒体,
原生支持不用急。
Canvas 绘图像素级,
游戏图表都适宜。

SVG 是矢量,
缩放不失真。
图标地图用它好,
交互简单又方便。

性能对比要记牢:
对象多用 Canvas,
交互频繁用 SVG,
根据场景来选择!

八、推荐资源


九、总结一句话

  • audio/video: 原生播放 + 丰富 API = 告别 Flash 时代 🎬
  • Canvas: 像素渲染 + 高性能 = 游戏图表利器 🎨
  • SVG: 矢量图形 + DOM 支持 = 图标地图首选 📊
最近更新