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

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

核心实现

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的响应式更新机制

相关推荐
zhoxier5 分钟前
element-ui 的el-table,多选翻页后,之前选择的数据丢失问题处理
vue.js·ui·elementui
Oriel11 分钟前
Strapi对接OSS:私有链接导致富文本图片过期问题的解决方案
前端
栀一一18 分钟前
@click和@click.stop的区别
vue.js
noodb软件工作室19 分钟前
支持中文搜索的markdown轻量级笔记flatnotes来了
前端·后端
Midsummer25 分钟前
nuxt安装报错-网络问题
vue.js·nuxt.js
张童瑶25 分钟前
Vue Electron 使用来给若依系统打包成exe程序,出现登录成功但是不跳转页面(已解决)
javascript·vue.js·electron
火柴就是我37 分钟前
每日见闻之<script type="module"> 的含义与作用
javascript
Catfood_Eason38 分钟前
HTML5 盒子模型
前端·html
小李小李不讲道理44 分钟前
「Ant Design 组件库探索」二:Tag组件
前端·react.js·ant design