视频编辑器时间轴刻度尺的实现

在视频编辑器中,时间轴刻度尺是一个非常重要的组件,它能直观地展示视频的时间位置。今天我们来详细讲解一下时间轴刻度尺的实现原理。

核心实现

1. Canvas绘制基础

时间轴刻度尺使用Canvas实现,主要包含以下几个关键点:

js 复制代码
const canvas = document.getElementById('time-ruler-canvas');
const ctx = canvas.getContext('2d');
canvas.width = timeline.lengthInpx; // 画布宽度根据时间轴长度动态设置
ctx.strokeStyle = '#353535';  // 设置刻度线颜色

2. 刻度绘制逻辑

刻度的绘制采用分级显示的方式:

  • 普通刻度:3px高

  • 5的倍数刻度:6px高

  • 10的倍数刻度:16px高,并显示时间文本

具体实现代码:

js 复制代码
function drawTick(tick, unit) {
  let length = 3;
  ctx.lineWidth = 1;
  
  // 判断刻度等级
  if (tick % 5 === 0) length = 6;
  if (tick % 10 === 0) length = 16;

  // 画刻度线
  ctx.moveTo(tick * timeline.scale * unit, 0);
  ctx.lineTo(tick * timeline.scale * unit, length);
  ctx.stroke();

  // 在10的倍数刻度处绘制时间文本
  if (tick % 10 === 0) {
    ctx.fillStyle = '#9f9f9f';
    ctx.fillText(sec2hsm(tick * unit), tick * timeline.scale * unit + 2, length);
  }
}

Tip: sec2hsm 是一个工具方法,把64s转换成01:04

3. 比例尺算法

比例尺(scale)决定了时间轴的显示密度。在代码中,scale表示1秒在画布上占用的像素数。比如:

  • scale = 10 表示 1秒 = 10px

  • scale = 20 表示 1秒 = 20px

为了保证刻度的清晰可读,设计一个自适应的刻度单位池:

js 复制代码
const unitPool = [
  { scale: 45, unit: 1/10 },  // 比例尺>=45px时,1个刻度表示0.1秒
  { scale: 20, unit: 1 },     // 比例尺>=20px时,1个刻度表示1秒
  { scale: 10, unit: 2 },     // 比例尺>=10px时,1个刻度表示2秒
  { scale: 4, unit: 3 },      // 比例尺>=4px时,1个刻度表示3秒
  { scale: 1, unit: 6 }       // 比例尺>=1px时,1个刻度表示6秒
];

根据当前的scale值,自动选择合适的刻度单位:

js 复制代码
const unit = unitPool.find((u) => u.scale <= timeline.scale).unit;

4. 缩放实现

缩放的实现主要依赖于Timeline类中的scale属性:

js 复制代码
// Timeline.js
constructor(options) {
  const defaults = {
    scale: 10, // 默认10px = 1s
    // ...其他属性
  }
}

get lengthInpx() {
  return this.end * this.scale * 1.2; // 时间轴总长度 = 总时长 * 比例尺 * 1.2
}

当用户进行缩放操作时,只需要改变scale值,TimeRuler组件会通过Vue的响应式系统自动重新渲染:

js 复制代码
watch(() => timeline.lengthInpx, drawTimeRuler, {
  immediate: true,
  deep: true
});

为了优化性能,使用了throttle防抖处理,减少滚动鼠标滚轮时的触发间隔:

js 复制代码
const drawTimeRuler = throttle(function () {
  canvas.width = Math.min(timeline.lengthInpx, 65535) // 清除画布,宽度最大65535,超出会崩溃
  ctx.strokeStyle = '#353535'

  const unitPool = [
    { scale: 45, unit: 1 / 10 },
    { scale: 20, unit: 1 },
    { scale: 10, unit: 2 },
    { scale: 4, unit: 3 }, // 比例尺4px = 1s,则一个刻度表示3秒
    { scale: 1, unit: 6 } // 比例尺1px = 1s,则一个刻度表示6秒
  ]
  const unit = unitPool.find((u) => u.scale <= timeline.scale).unit
  const tickCount = canvas.width / timeline.scale / unit
  for (let i = 0; i < tickCount; i++) {
    drawTick(i, unit)
  }
}, 200)

总结

时间轴刻度尺的实现核心在于:

  • 使用Canvas进行高效绘制

  • 采用分级刻度显示策略

  • 动态比例尺算法

  • 基于Vue的响应式更新机制

相关推荐
集成显卡13 小时前
Bun v1.3.6 发布:内置 Tarball 归档支持、JSONC 解析、Bundle 分析增强等重磅更新!
javascript·新版本·bun.js
奔跑的web.13 小时前
TypeScript Enum 类型入门:从基础到实战
前端·javascript·typescript
盐真卿13 小时前
python2
java·前端·javascript
梦梦代码精14 小时前
BuildingAI vs Dify vs 扣子:三大开源智能体平台架构风格对比
开发语言·前端·数据库·后端·架构·开源·推荐算法
刘一说14 小时前
Vue3 组合式 API(Composition API):逻辑复用的革命性实践
vue.js·vue
seabirdssss15 小时前
《bootstrap is not defined 导致“获取配置详情失败”?一次前端踩坑实录》
前端·bootstrap·html
kgduu15 小时前
js之表单
开发语言·前端·javascript
摘星编程16 小时前
React Native for OpenHarmony 实战:Picker 选择器组件详解
javascript·react native·react.js
摘星编程16 小时前
React Native for OpenHarmony 实战:VirtualizedList 虚拟化列表
javascript·react native·react.js
谢尔登17 小时前
Vue3 响应式系统——computed 和 watch
前端·架构