vue-time-axis-plus进阶:双进度条+跨空白续播+播放指针,打造专业级监控回放体验

入门篇跑通了基础功能,但实际监控回放场景还需要:全天录像概览(双进度条)、播放指针居中跟随、点击空白自动续播。这篇文章把这些进阶功能都实现了。


一、双进度条:主时间轴+全天概览

1.1 什么是双进度条?

复制代码
┌─────────────────────────────────────────┐  ← 主时间轴(可缩放)
│  ████    ████████████    ████████      │
├─────────────────────────────────────────┤  ← 概览条(全天)
│ ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ │
│      ↑可视窗口        ↑播放位置         │
└─────────────────────────────────────────┘
  • 主时间轴:可缩放、可拖动,显示当前视口的细节
  • 概览条:显示全天的录像分布,可快速跳转

1.2 启用概览条

vue 复制代码
<VueTimeAxisPlus
  :start-time="startTime"
  :segments="segments"
  :overview="true"
  :overview-height="20"
/>

1.3 运行时动态开关

vue 复制代码
<template>
  <VueTimeAxisPlus ref="timeline" :segments="segments" />
  <button @click="$refs.timeline.updateOptions({ overview: true })">显示概览条</button>
  <button @click="$refs.timeline.updateOptions({ overview: false })">隐藏概览条</button>
</template>

1.4 概览条点击跳转

点击概览条会触发changeTime事件,可以实现快速跳转:

javascript 复制代码
onChangeTime(data) {
  // 点击概览条时,mode为'click'
  // timestamp为点击位置对应的时间
  this.seekTo(data.timestamp)
}

二、播放指针居中跟随

2.1 问题

播放时,指针移动到视口边缘就看不到了。

2.2 解决方案

启用centerPointer,播放时自动滚动视口使指针居中:

vue 复制代码
<VueTimeAxisPlus
  ref="timeline"
  :center-pointer="true"
  @playTime="onPlayTime"
/>

2.3 播放逻辑实现

javascript 复制代码
data() {
  return {
    playing: false,
    playTimer: null,
    playTime: 0
  }
},
methods: {
  onPlayTime(data) {
    // data.timestamp: 当前播放时间
    // data.valid: 是否在有效录像内

    if (!data.valid) {
      // 进入空白区域,查下一段续播
      const next = this.$refs.timeline.getNextSegment(data.timestamp)
      if (next) {
        this.playTime = next.begin
        this.$refs.timeline.updateTime(this.playTime)
      }
    }
  },

  startPlay() {
    this.playing = true
    this.playTimer = setInterval(() => {
      this.playTime += 1000  // 每秒前进1秒
      if (this.playTime >= this.maxTime) {
        this.stopPlay()
        return
      }
      this.$refs.timeline.updateTime(this.playTime)
    }, 1000)
  },

  stopPlay() {
    this.playing = false
    clearInterval(this.playTimer)
  }
}

2.4 手势让位后自动恢复

用户拖动时间轴时,播放指针暂停跟随;松手后自动恢复:

vue 复制代码
<VueTimeAxisPlus
  :center-pointer="true"
  :center-resume-delay="3000"  // 3秒后自动恢复居中
/>

三、跨空白续播

3.1 问题

录像有空白时段(如夜间无录像),用户点击空白区域时怎么处理?

3.2 解决方案

启用snapToNearest,点击空白自动吸附到最近的片段起点:

vue 复制代码
<VueTimeAxisPlus
  :snap-to-nearest="true"
  @changeTime="onChangeTime"
/>

3.3 续播逻辑

javascript 复制代码
onChangeTime(data) {
  if (data.mode === 'snap') {
    // 被吸附到了下一段起点
    console.log(`自动跳转到 ${new Date(data.nextBegin.begin).toLocaleTimeString()}`)

    // 开始播放下一段
    this.playTime = data.nextBegin.begin
    this.startPlay()
  }
}

3.4 getNextSegment查询

不依赖snap,手动查询下一段:

javascript 复制代码
// 从当前时间往后找最近的录像片段
const next = this.$refs.timeline.getNextSegment(this.playTime)
if (next) {
  console.log(`下一段: ${new Date(next.begin).toLocaleTimeString()} - ${new Date(next.end).toLocaleTimeString()}`)
  console.log(`业务字段: ${next.id}`)
}

3.5 getNextSegments批量查询

获取从当前时间往后的所有片段(可做播放列表):

javascript 复制代码
const playlist = this.$refs.timeline.getNextSegments(this.playTime)
console.log(`还有 ${playlist.length} 段录像`)

四、自定义样式

4.1 axisStyle配置

vue 复制代码
<VueTimeAxisPlus
  :axis-style="{
    borderColor: '#333',
    graduationColor: '#666',
    tickTextColor: '#fff',
    hoverLineColor: '#00ff00',
    hoverTextColor: '#00ff00',
    overviewBg: '#1a1a1a',
    overviewWindowColor: 'rgba(64, 196, 255, 0.2)',
    overviewWindowBorder: '#40c4ff',
    overviewPlayColor: '#ff5c5c'
  }"
/>

4.2 片段样式

每个片段可以独立设置样式:

javascript 复制代码
segments: [
  {
    begin: t(6), end: t(7),
    style: { background: 'rgba(24,208,217,0.5)' }  // 青色
  },
  {
    begin: t(7), end: t(8),
    style: { background: 'rgba(255,77,79,0.6)' }    // 红色
  },
  {
    begin: t(8), end: t(9),
    style: { background: 'rgba(255,165,0,0.5)' }    // 橙色
  }
]

4.3 主题切换

javascript 复制代码
const darkTheme = {
  tickTextColor: '#ccc',
  overviewBg: '#1a1a1a',
  overviewWindowColor: 'rgba(64, 196, 255, 0.15)'
}

const lightTheme = {
  tickTextColor: '#333',
  overviewBg: '#f5f5f5',
  overviewWindowColor: 'rgba(64, 196, 255, 0.1)'
}

const switchTheme = (theme) => {
  this.$refs.timeline.updateOptions({ axisStyle: theme })
}

五、踩坑记录

坑1:播放指针居中与手势冲突

现象:用户拖动时间轴时,播放指针还在居中跟随,导致视口跳动。

原因:centerPointer和用户手势同时生效。

解决:组件内部已处理,用户手势时自动暂停居中,松手后延迟恢复。

坑2:概览条动态开关后高度不对

现象:运行时切换overview后,时间轴高度没有变化。

原因:没有调用updateOptions。

解决:

javascript 复制代码
this.$refs.timeline.updateOptions({ overview: true })
// 组件内部会自动重算画布高度

坑3:getNextSegment返回null

现象:调用getNextSegment后返回null。

原因:当前时间已经是最后一段之后。

解决:判断返回值:

javascript 复制代码
const next = this.$refs.timeline.getNextSegment(time)
if (next) {
  // 有下一段
} else {
  // 已经是最后一段之后
}

六、总结

功能 配置 关键点
概览条 overview: true 支持运行时动态开关
播放指针居中 centerPointer: true 手势时自动暂停
跨空白续播 snapToNearest: true 点击空白自动吸附
查询下一段 getNextSegment(time) 返回完整片段信息
主题切换 updateOptions({axisStyle}) 支持部分字段覆盖

更新日期 :2026年9月

调试版本:vue-time-axis-plus 1.x / Vue 3.4+

相关推荐
樱花落木兰7 分钟前
分布式登录实战:Session 会话共享改造,Redis 存储用户登录状态
java·javascript·数据库·redis·分布式·缓存
Helix25010 分钟前
Chrome 开发者工具进阶:长截图、网络调试与性能分析
前端·chrome·chrome devtools·使用技巧·性能分析·开发者工具·长截图
liangshanbo121536 分钟前
面试题:线上 JavaScript 报错如何快速定位到源码?
开发语言·javascript·ecmascript
liangshanbo121537 分钟前
面试题:Webpack 的 publicPath 有什么作用?
前端·webpack·node.js
mjhcsp38 分钟前
DeepSeek V4.1 Flash 批量处理效能实测
java·前端·数据库
CHEEVEN_QY2 小时前
新能源汽车电池托盘FSW量产的工艺稳定性控制
java·前端·汽车
Alice-YUE2 小时前
前端 × AI:从 Cursor 到 Transformer,一份完整认知路径
前端·人工智能·transformer·ai编程·前端开发·cursor
Code_Solitude2 小时前
C语言:关于二维数组的作业总结
java·c语言·前端
专业程序开发源2 小时前
django新闻推荐系统70655-计算机课程设计、毕业设计
java·javascript·spring boot·后端·python·django·课程设计
acd120093 小时前
前端随笔:数据明明变了,Vue 页面就是不更新
前端·javascript·vue.js