npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@flow-player/timeline

v0.14.2

Published

Canvas timeline widget for Flow Player VOD playback: segment highlighting, event markers, zoom/pan interaction and playback cursor, designed to pair with @flow-player/browser-runtime VOD players (supports headless renderer for custom paint layers).

Readme

@flow-player/timeline

框架无关的 Canvas VOD 回放时间轴。默认采用 24 小时固定中心播放头,支持 Pointer Events、DPR、ResizeObserver、播放器外部时钟、区间异常、键盘/基础触控 和完整生命周期管理。

能力

  • 默认 24 小时视图,可配置 1 分钟至 31 天缩放范围
  • none / viewport / playhead 三种跨界策略
  • 顶部或底部三级刻度,支持 locale、timeZone、自定义 formatter(按级别/日边界)和 DST 日界线
  • 刻度档位候选表与最小像素间距可配置(tickCandidates / tickMinSpacingPx)
  • 固定中心播放头、hover 准星、点击选时、拖动预览/单次提交、滚轮锚点缩放
  • 拖拽默认采用地图式平移(右拖 = 时间后退),可用 dragInvertsTime 反转为右拖 = 时间前进
  • 常规、事件、报警录像段,逐段样式覆写,自定义 marker 与 gap/overlap 区间
  • 宿主 design token、内部工具栏、状态徽标和动态主题/几何更新
  • renderer: "none" headless 模式:只保留交互/键盘/aria/状态机,宿主自绘画布
  • 方向键、Home/End、+/-、0、Escape,以及不劫持纵向滚动的基础触控
  • 播放器 timeupdate 外部驱动或 startAutoAdvance() 内部推进;两种时钟互斥
  • DPR、显式/自动 resize、rAF 合帧和 destroy() 完整清理

基本用法

import { FlowTimeline } from "@flow-player/timeline";

const dayStartMs = Date.parse("2026-08-27T00:00:00+08:00");
const timeline = new FlowTimeline({
  container: document.getElementById("timeline")!,
  centerMs: dayStartMs,
  bounds: { startMs: dayStartMs, endMs: dayStartMs + 86_400_000 },
  boundaryMode: "playhead",
  locale: "zh-CN",
  timeZone: "Asia/Shanghai",
  segments: [
    { startMs: dayStartMs + 3_600_000, endMs: dayStartMs + 7_200_000, kind: "continuous" },
    { startMs: dayStartMs + 8_000_000, endMs: dayStartMs + 8_600_000, kind: "event" },
  ],
  issues: [
    { startMs: dayStartMs + 7_200_000, endMs: dayStartMs + 8_000_000, kind: "gap" },
  ],
  tokens: {
    surface: "rgba(11, 23, 27, 0.96)",
    track: "rgba(24, 49, 56, 0.72)",
    playhead: "rgba(255, 107, 53, 0.95)",
    continuous: "rgba(38, 201, 154, 0.9)",
    event: "rgba(242, 191, 75, 0.9)",
  },
  toolbarVisibility: {
    currentTime: true,
    status: true,
    legend: false,
    dayReset: false,
  },
  onScrubPreview: ({ timestampMs }) => showPreview(timestampMs),
  onSeekRequest: ({ timestampMs }) => player.seek(timestampMs),
});

player.addEventListener("timeupdate", (event) => {
  timeline.setCursorTime(event.detail.positionMs, "playing");
});

timeline.destroy();

所有颜色 token 都接受浏览器支持的 CSS color string,包括十六进制、rgb()、 rgba()、hsl() 和 oklch()。常用映射:事件类型使用 continuous / event / alarm / gap / overlap,时间条底色使用 track,中心指针使用 playhead / playheadPaused,组件与工具栏背景分别使用 surface / toolbarSurface。

工具栏自由组合

toolbarVisibility 可独立控制 currentTime、status、legend、zoomOut、 dayReset、zoomIn 和 recenter。showToolbar: false 仍是工具栏总开关;若所有 子项均隐藏,工具栏会折叠且不占高度。

timeline.setToolbarVisibility({
  currentTime: false,
  status: false,
  legend: false,
  dayReset: false,
});

运行时可多次调用 setToolbarVisibility() 做部分更新,未传字段保持原值。

数据与交互

  • TimelineSegment 用 kind 表达业务语义,并允许 style 覆写 fill、stroke、opacity、height。
  • TimelineMarker 支持独立线条、字体、文字偏移和 formatter。
  • TimelineIssue 用完整区间表达 gap / overlap,而不是退化成单点标记。
  • 拖动期间只触发 onScrubPreview;松手触发一次 onScrubCommit 和 onSeekRequest。点击事件提交实际点击时刻,不会跳到整段起点。
  • dragInvertsTime 缺省为 false:时间轴像地图一样跟随手指,右拖时中心时刻变早。 设为 true 后改为时间方向语义,右拖时中心时刻变晚。跨天是否切换业务日 仍由宿主根据 onViewChange / onSeekRequest 处理;boundaryMode 只负责限制视图或中心播放头。
  • onViewChange / onCenterChange 携带 source,可区分 player、drag、click、 wheel、keyboard、toolbar、auto 与 API。

source 语义矩阵

| source | 触发时机 | | --- | --- | | api | 外部调用 setCenterTime() / changeZoom() / setViewSpan() 等公开 API(未显式传 source 时) | | player | 外部以 setCenterTime(ms, "player") 上报播放器时钟(如 timeupdate 驱动游标) | | drag | 时间轴拖动(scrub)导致的中心/视图变化 | | click | 单击时间轴跳转 | | wheel | 滚轮缩放 | | keyboard | 键盘(方向键/Home/End/缩放键) | | toolbar | 工具栏按钮(zoom in/out、24h、回中) | | auto | startAutoAdvance 内部自动推进 |

注意:setCenterTime() 缺省 source 即 api,也会触发 onCenterChange——外部 驱动游标时如需静默,请用 player source 并按 source 过滤。

Headless 渲染与自绘层

renderer: "none" 进入 headless 模式:不执行任何 Canvas 绘制、不显示 hover 气泡 DOM、不注入 focus boxShadow——只保留交互/键盘/aria/视图状态机与全部事件 回调。适合宿主自绘画布叠加透明交互层、自行还原行业视觉约定的场景。

const timeline = new FlowTimeline({
  container,
  renderer: "none", // 只保留交互与状态机
});
// 自绘层对齐尺寸:免旁路 ResizeObserver
const w = timeline.getWidth();
const h = timeline.getHeight();

headless 模式下 onSegmentClick / onMarkerClick 的命中区仍按内置布局几何 (graduationPosition + tokens 高度)判定;自绘层布局不同时请自行处理命中。

刻度定制

  • tickCandidates?: number[]:自定义刻度步长候选表(ms 升序),缺省用内置 TICK_CANDIDATES(1s…31d)。
  • tickMinSpacingPx?: number:刻度选档的最小像素间距,缺省 112。
  • formatters.tick 回调第 5/6 个参数为刻度级别(major | medium | minor)与 是否日边界(本地 0 点),可按级别区分格式;日边界文字可用 token textDayBoundary 独立配色(缺省回落 textMuted)。
  • centerTimeLabel?: { color?, formatter? }:在中心指针线顶部绘制当前时间 文字(跟随 showPlayhead;headless 下不绘制)。

跨天与缩放

| 配置 | 行为 | | --- | --- | | boundaryMode: "none" | 不限制跨天 | | boundaryMode: "viewport" | 整个视窗保持在 bounds 内 | | boundaryMode: "playhead" | 只限制中心播放头,视窗边缘可以跨界 |

zoomAnchorMs / setZoomAnchorTime() 可固定缩放基准;未设置时,滚轮与按钮、 API 一致以视口中心(当前时间)为锚——缩放只改档位,中心播放头与当前时间不动。 工具栏 24h 在存在全天 bounds 时恢复完整日历日,否则恢复当前播放头所在日历日。

自动推进

timeline.startAutoAdvance({
  startMs,
  endMs,
  rate: 2, // 2ms 时间轴 / 1ms 墙钟,即 2x
  intervalMs: 100,
});
timeline.stopAutoAdvance();

调用 setCursorTime()、开始拖动或销毁组件会停止内部推进,避免与真实播放器 时钟竞争。