资讯详情

lightweight-charts 时间轴(Time Scale)完全指南:可见范围、逻辑区间(Logical Range)与图表边距控制

📅 2026/9/21 2:39:51 | 华诺云谱 👁 阅读
lightweight-charts 时间轴(Time Scale)完全指南:可见范围、逻辑区间(Logical Range)与图表边距控制
lightweight-charts 时间轴Time Scale完全指南可见范围、逻辑区间Logical Range与图表边距控制【免费下载链接】lightweight-chartsPerformant financial charts built with HTML5 canvas项目地址: https://gitcode.com/gh_mirrors/li/lightweight-charts时间轴Time Scale也称时间轴刻度或 x 轴是 lightweight-charts 中位于图表底部的水平刻度负责展示各数据点K 线、折线等的时间并掌控图表的全部横向行为可见范围的读取与设置、时间点/逻辑索引与像素坐标的双向换算以及滚动、缩放等交互。本文以版本 4.0 官方文档 website/versioned_docs/version-4.0/time-scale.md 为主线结合当前仓库 v5.2.1见 package.json中ITimeScaleApi、TimeScale等源码实现系统讲解如何通过chart.timeScale()获取 API、理解并操作逻辑区间、控制可见范围与图表边距并订阅时间轴相关事件。Time scale认识时间轴从概念到 API 入口时间轴Time scale / time axis是图表底部的一条水平刻度线它显示每个 bar数据点对应的时间。它的职责不止于画刻度——它还控制当前可见范围visible range、允许你主动影响或修改该范围并能把时间点或索引index换算成 x 坐标或把坐标换算回时间/索引。简单来说凡是与图表横向x 轴方向相关的操作都归结到时间轴上。同时时间轴提供若干事件订阅接口当可见范围、逻辑区间或尺寸发生变化时你可以收到通知。要操作时间轴有两种途径通过IChartApi.timeScale方法获取ITimeScaleApi实例再调用其上的方法。接口定义见 src/api/itime-scale-api.ts具体实现见 src/api/time-scale-api.ts。通过选项options配置外观与行为。所有可用选项声明在TimeScaleOptions接口源码中为 src/model/time-scale.ts 的HorzScaleOptions中。关于选项的设置方式文档特别强调无论是通过ITimeScaleApi.applyOptions还是IChartApi.applyOptions把timeScale作为子对象传入两种方式效果完全等价。例如// 方式一通过 ITimeScaleApi chart.timeScale().applyOptions({ rightOffset: 5, barSpacing: 8 }); // 方式二通过 IChartApitimeScale 子对象 chart.applyOptions({ timeScale: { rightOffset: 5, barSpacing: 8 } });从源码看TimeScaleApi.applyOptions最终调用this._timeScale.applyOptions(options)src/api/time-scale-api.ts而IChartApi.applyOptions内部同样会把timeScale子对象下发到同一个TimeScale模型src/model/time-scale.ts因此两种写法最终作用于同一套状态。时间轴在架构中的位置从源码结构看时间轴由三层协作完成TimeScale模型层位于 src/model/time-scale.ts保存时间点数据_points、可见范围_visibleRange、barSpacing、rightOffset等核心状态并提供索引/坐标换算与可见范围计算的核心逻辑。TimeScaleApiAPI 层位于 src/api/time-scale-api.ts对模型层做包装向用户暴露ITimeScaleApi接口它还负责把模型层的Delegate事件如visibleBarsChanged、logicalRangeChanged、sizeChanged转发为用户可订阅的回调。TimeAxisWidgetGUI 层位于 src/gui/time-axis-widget.ts负责把刻度标签实际绘制到画布底部其尺寸变化也通过sizeChanged事件暴露出来src/api/time-scale-api.ts。逻辑区间Logical Range理解连续的时间轴什么是逻辑区间逻辑区间logical range是一个包含from和to两个数字属性的对象这两个数字表示时间轴上的逻辑索引logical index。类型定义见 src/model/time-data.ts 的LogicalRangeexport type LogicalRange IRangeLogical; // { from: Logical; to: Logical }关键语义如下逻辑区间的起点是全部序列中的第一个数据项。在这一点之前所有索引为负数从这一点开始索引为正数。索引可以带小数部分例如4.2因为时间轴是连续的而不是离散的。整数部分表示完全可见的 bar 的索引。例如最后一个可见逻辑索引to字段是5.2说明最后一根完全可见的 bar 索引是 5同时还露出了第 6 根 bar 的 20%。0.5如1.5、3.5、10.5恰好表示一根 bar 的正中间。Logical range上图中红色竖线是相邻 bar 之间的边界因此该图表的可见逻辑区间大约为从-4.73到5.05。从源码印证逻辑区间的换算TimeScale模型把逻辑索引与像素坐标的换算集中实现indexToCoordinate(index)src/model/time-scale.ts把逻辑索引换算为 x 坐标核心公式为const baseIndex this.baseIndex(); const deltaFromRight baseIndex this._rightOffset - index; const coordinate this._width - (deltaFromRight 0.5) * this._barSpacing - 1;可见坐标由barSpacing、rightOffset与宽度共同决定其中0.5的偏移意味着 bar 的中心点而非左边界作为基准位置与0.5 表示 bar 正中的语义一致。coordinateToIndex(x)src/model/time-scale.ts则反向把 x 坐标换算为逻辑索引取Math.ceil保证返回的是整数 bar 索引。这两者正对应ITimeScaleApi中的logicalToCoordinate与coordinateToLogicalsrc/api/itime-scale-api.ts。若图表没有任何数据这两个方法会返回null。可见范围Visible Range数据区间与逻辑区间两种度量可见范围指当前画布上实际显示出来的图表区域它可以同时用两种方式度量数据区间data range包含从第一根可见 bar 到最后一根可见 bar 的时间戳。如果可见区域存在空白没有数据的部分该空白不纳入数据区间。逻辑区间logical range以逻辑索引度量的连续范围见上一节。ITimeScaleApi提供四个成对的方法来读写这两种区间src/api/itime-scale-api.ts方法作用getVisibleRange()返回当前可见的数据时间区间IRangeTime \| null无数据时返回nullsetVisibleRange(range)设置可见的数据时间区间getVisibleLogicalRange()返回当前可见逻辑区间LogicalRange \| nullsetVisibleLogicalRange(range)设置可见逻辑区间可超出数据边界setVisibleRange无法外推时间官方文档特别提醒setVisibleRange不能外推extrapolate时间它只会使用当前已存在的数据。例如图表在2018-01-01之前没有任何数据此时设置可见区间from为2016-01-01会被自动修正为2018-01-01to同理。源码中对应TimeScale.logicalRangeForTimeRangesrc/model/time-scale.ts它通过timeToIndex(range.from, true)与timeToIndex(range.to, true)把时间换算成索引findNearest true意味着找不到精确时间点时自动吸附到最近的数据点。官方示例注意时间使用秒级时间戳chart.timeScale().setVisibleRange({ from: (new Date(Date.UTC(2018, 0, 1, 0, 0, 0, 0))).getTime() / 1000, to: (new Date(Date.UTC(2018, 1, 1, 0, 0, 0, 0))).getTime() / 1000, });如果你能自行估算索引建议改用setVisibleLogicalRange它的灵活性更高chart.timeScale().setVisibleLogicalRange({ from: 0, to: 10 });源码层面setVisibleLogicalRange会先断言from to随后调用this._model.setTargetLogicalRange(range)src/api/time-scale-api.ts。其他可见范围相关方法fitContent()自动计算可见范围让所有序列的数据全部适配进图表src/api/itime-scale-api.ts。实现委托给_model.fitContent()。resetTimeScale()恢复时间轴的默认缩放级别与滚动位置src/api/itime-scale-api.ts。scrollPosition()/scrollToPosition(position, animated)返回/设置从时间轴右边缘到最新一根 bar 的距离以 bar 数为单位。animatedtrue时平滑滚动动画时长在实现中为 1000mssrc/api/time-scale-api.ts。scrollToRealTime()恢复到实时最新数据位置该过程始终带动画src/api/itime-scale-api.ts。图表边距Chart MarginbarSpacing 与 rightOffset 的作用边距margin是图表边框与序列之间的空白距离它由两个时间轴选项决定barSpacing相邻 bar 之间的像素间距默认值6。rightOffset图表右侧的空白以 bar 数为单位默认值0。这两个选项可以在创建图表时传入也可以用上一节介绍的方式动态修改。数据点较少时的边距问题官方文档指出如果序列只有少量数据点图表左侧可能出现很大的边距。此时可以调用fitContent()来适配视图让所有数据完整显示chart.timeScale().fitContent();但如果调用fitContent没有效果原因在于库的渲染机制库会为每个数据点分配固定的宽度以在不同图表类型之间保持一致性。例如折线序列的数据点位于该分配宽度的中心而 K 线序列则用大部分宽度来绘制实体。分配给每个数据点的空间与图表宽度成正比因此数据点较少的序列可能在两侧都出现小边距。A series with a few points用逻辑区间精确贴边如果你希望序列精确贴到图表边缘文档推荐通过setVisibleLogicalRange显式指定逻辑区间。下面这个示例在现有可见范围基础上左右各收缩半根 bar 的宽度const vr chart.timeScale().getVisibleLogicalRange(); chart.timeScale().setVisibleLogicalRange({ from: vr.from 0.5, to: vr.to - 0.5 });Margin由于逻辑索引的 0.5 恰好是 bar 的中心见前文逻辑区间一节0.5 / -0.5正好把可见范围从 bar 边界收紧到两根 bar 的中心线从而去掉两侧的半根 bar 边距。源码佐证rightOffset 与 barSpacing 的底层行为从源码看这两个选项与滚动/缩放的实现紧密耦合setRightOffset(offset)src/model/time-scale.ts会置_visibleRangeInvalidated随后调用_correctOffset()防止滚动超出可见 bar 的范围并触发整图重算与轻量刷新。setBarSpacing(newBarSpacing)src/model/time-scale.ts在更新间距后会调用_correctOffset()当设置了rightOffsetPixels像素级右偏移时缩放还会按比例重算 bar 级偏移以保证像素偏移量在缩放前后保持不变。applyOptions内部对选项的应用顺序也做了约束barSpacing必须先于rightOffset应用因为 rightOffset 依赖 barSpacing 计算src/model/time-scale.ts 的注释明确说明了这一点。坐标与时间双向换算桥接交互与数据ITimeScaleApi提供了一组换算方法非常适合实现十字光标、Tooltip、标记定位等交互功能src/api/itime-scale-api.ts方法方向说明timeToCoordinate(time)时间 → 坐标把时间换算为局部 x 坐标找不到该时间时返回nullcoordinateToTime(x)坐标 → 时间返回该坐标处 bar 的时间该坐标无 bar 时返回nulltimeToIndex(time, findNearest?)时间 → 索引返回时间点索引findNearesttrue时吸附最近点logicalToCoordinate(logical)逻辑索引 → 坐标图表无数据时返回nullcoordinateToLogical(x)坐标 → 逻辑索引图表无数据时返回nullwidth()/height()尺寸返回时间轴的宽高像素以timeToCoordinate为例其实现先通过timeToIndex(time, false)精确查找索引查不到返回null再委托indexToCoordinate换算坐标src/api/time-scale-api.ts而coordinateToTime则先coordinateToIndex得到索引再经indexToTimeScalePoint取出原始时间src/api/time-scale-api.ts。事件订阅感知可见范围与尺寸的变化时间轴提供了三组可订阅事件回调类型定义在 src/api/itime-scale-api.ts可见时间区间变化subscribeVisibleTimeRangeChange(handler)/unsubscribeVisibleTimeRangeChange(handler)回调参数为IRangeTime | null无可见数据时为null。可见逻辑区间变化subscribeVisibleLogicalRangeChange(handler)/unsubscribeVisibleLogicalRangeChange(handler)回调参数为LogicalRange | null。尺寸变化subscribeSizeChange(handler)/unsubscribeSizeChange(handler)回调参数为(width, height)。官方示例可见时间区间function myVisibleTimeRangeChangeHandler(newVisibleTimeRange) { if (newVisibleTimeRange null) { // 处理 null无可见数据 } // 处理新的可见区间 } chart.timeScale().subscribeVisibleTimeRangeChange(myVisibleTimeRangeChangeHandler); // 取消订阅 chart.timeScale().unsubscribeVisibleTimeRangeChange(myVisibleTimeRangeChangeHandler);逻辑区间订阅的用法完全对称function myVisibleLogicalRangeChangeHandler(newVisibleLogicalRange) { if (newVisibleLogicalRange null) { // 处理 null } // 处理新的逻辑区间 } chart.timeScale().subscribeVisibleLogicalRangeChange(myVisibleLogicalRangeChangeHandler); chart.timeScale().unsubscribeVisibleLogicalRangeChange(myVisibleLogicalRangeChangeHandler);从源码看TimeScaleApi的构造函数把模型层的三个事件visibleBarsChanged、logicalRangeChanged、sizeChanged分别转发到对应的Delegate上src/api/time-scale-api.ts并在内部回调里把null情况一并透传给订阅者src/api/time-scale-api.ts。因此即使图表暂时没有数据回调也会收到null而不是不触发处理时务必判空。总结时间轴操作速查需求推荐 API获取时间轴 APIchart.timeScale()读取/设置可见时间区间getVisibleRange()/setVisibleRange()读取/设置可见逻辑区间getVisibleLogicalRange()/setVisibleLogicalRange()一键适配全部数据fitContent()恢复默认缩放与位置resetTimeScale()滚动到指定位置 / 实时位置scrollToPosition()/scrollToRealTime()时间 ↔ 坐标 ↔ 索引换算timeToCoordinate/coordinateToTime/timeToIndex/logicalToCoordinate/coordinateToLogical修改时间轴选项timeScale().applyOptions()或chart.applyOptions({ timeScale: {...} })订阅可见范围/尺寸变化subscribeVisibleTimeRangeChange/subscribeVisibleLogicalRangeChange/subscribeSizeChange要点回顾逻辑区间以第一个数据项为 0 点前后分别为负数与正数索引可带小数整数部分是完整可见的 barx.5是 bar 正中。setVisibleRange不能外推时间会吸附到已有数据需要灵活控制可见范围时使用setVisibleLogicalRange。边距由barSpacing与rightOffset控制数据点少时可用fitContent或精确设置逻辑区间来消除多余边距。时间轴事件在无数据时会回调null订阅时记得判空。【免费下载链接】lightweight-chartsPerformant financial charts built with HTML5 canvas项目地址: https://gitcode.com/gh_mirrors/li/lightweight-charts创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。