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

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

核心实现

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

相关推荐
2分钟速写快排14 分钟前
什么是 RAG?如何用 RAG 实现一个用户记忆?
前端·后端·ai编程
passerby60611 小时前
如何自己造一个时间处理库
前端·javascript·github
走到天涯海角2 小时前
react里面的长列表渲染优化
前端·react.js·前端框架
小羊没烦恼!2 小时前
Hello Web API系列教程——Web API与国际化
java·服务器·前端·javascript·php
北岛贰2 小时前
迷茫焦虑期,我做了一个带支付带官网的 AI 聊天虚拟恋人 App
前端·人工智能·后端
mayaairi4 小时前
Vue2 组件通讯(三):全局事件总线、PubSub、插槽与组件实例属性
前端·javascript·vue.js
kyriewen4 小时前
面试官问我:AI 都能写代码了,前端凭什么还值 25K
前端·javascript·人工智能
风骏时光牛马5 小时前
AI源码分析:拆解模型底层实现逻辑
前端
BillKu5 小时前
全局样式变量:CSS 自定义属性(--border-color)和SCSS 变量($border-color)的说明
javascript·css·scss
IT_陈寒5 小时前
React子组件莫名其妙重渲染?你可能漏了这个Hook
前端·人工智能·后端