故障排查
可复制的检查与修复,用于常见图表集成失败情况。
这些故障模式源自与 diagnose_chart 使用相同的版本化知识。请从最匹配应用程序的症状开始,执行诊断检查,并仅保留那些保留已记录生命周期和类型数组所有权约定的修复。
如果没有条目匹配,请检查嵌套 API 参考中的相关符号,或请求本地 MCP 服务器运行针对性诊断。仅将复现缩减为 renderMode: "main" 和 animated: false 作为诊断步骤,而非自动的生产配置。
症状索引
画布为空白或尺寸为零
适用于:line,stock。
症状:图表初始化时未显示错误,但未出现绘图或画布高度测量为零。
可能原因:渲染器初始化时画布宿主没有具体高度。
检查
- 使用 getBoundingClientRect() 检查宿主和画布;宽度和高度都必须大于零。
- 检查是否有 flex 或 grid 祖先折叠了图表行。
修复
- 在 initialize() 运行前为宿主设置具体的 height 或 min-height。
- 让画布填充该宿主,而不要依赖画布的内在尺寸。
为图表提供可测量的宿主
.chart-host {
position: relative;
width: 100%;
height: clamp(20rem, 55vh, 34rem);
}
.chart-host > canvas {
display: block;
width: 100%;
height: 100%;
}数据在图表就绪前被安装
适用于:line,stock。
症状:第一个数据集未出现,而后续更新或重新挂载有效。
可能原因:在 initialize() 完成前,原生集成调用了数据方法,或对同一画布初始化了多次。
检查
- 确认对每个图表实例严格等待 initialize() 一次。
- 如果框架管理视图,优先使用官方适配器,以便为你处理挂载与卸载顺序。
修复
- 在调用 setData() 或 setMultiSeriesData() 之前等待 initialize()。
- 在重用画布给另一个实例之前销毁旧图表。
按顺序使用原生生命周期
const chart = new LineChart(canvas, { renderMode: "auto" });
await chart.initialize();
chart.setData(data);
// Call this when the view is permanently removed.
export function disposeChart() {
chart.destroy();
}Worker 渲染回退到主线程
适用范围:line,stock。
症状。 图表可以工作,但解析为主线程渲染,或仅在生产环境中 worker 构造失败。
可能原因。 Worker、OffscreenCanvas、transferControlToOffscreen,或已部署的内容安全策略阻止了 worker 渲染器启动。
检查
- 临时使用 setStatsCallback() 并检查统计信息。renderMode。
- 检查浏览器控制台和 worker-src 内容安全策略指令。
修复
- 除非为诊断需要强制模式,否则保持 renderMode 设置为 auto。
- 在 worker-src 中允许应用生成的 worker URL,并保持主线程回退可用。
确认解析出的渲染器
chart.setStatsCallback((stats) => {
console.info("Sixtyfold renderer:", stats.renderMode);
chart.setStatsCallback(null);
});在将数据传递给 Worker 支持的图表后,类型化数组在 setData 后变为 detached
适用范围:line,stock。
症状。 源类型化数组的 byteLength 为 0,或在数据传给 worker 支持的图表后无法再读取。
可能原因。 在 worker 模式下,批量图表数据被转移到渲染器;被转移的 ArrayBuffers 会离开调用方。
检查
- 在批量数据调用前后立即检查 byteLength。
- 确认是否有其他子系统确实需要保留可读副本。
修复
- 将批量数据调用视为所有权转移。
- 仅克隆其他子系统必须保留的列;默认避免复制数百万值的数据集。
保留一个有意的应用副本
const retainedX = sourceX.slice();
const retainedY = sourceY.slice();
chart.setData({
x: sourceX,
y: sourceY,
length: sourceX.length,
});
// retainedX and retainedY remain readable.时间轴被压缩、为空或在远未来
适用范围:line,stock。
症状。 刻度显示不合理的日期、可见范围塌缩或平移行为不可预测。
可能原因。 用作 X 列的值使用了秒或字符串而不是有序的有限纪元毫秒,或观测值未排序。
检查
- 检查首尾时间戳并用 new Date(value) 进行转换。
- 验证每个时间戳为有限且非递减。
修复
- 在创建 Float64Array 之前将纪元秒转换为毫秒。
- 在摄取时解析 ISO 日期一次,并在将完整观测拆分为列之前对其排序。
在摄取时规范化时间戳
const timestamp = Float64Array.from(rows, (row) => {
const value = Date.parse(row.recordedAt);
if (!Number.isFinite(value)) throw new TypeError("Invalid recordedAt value");
return value;
});列长度不同或包含无效数值
适用范围:line,stock。
症状。 图表拒绝数据集、意外截断或在错误时间戳下渲染值。
可能原因。 列式数据由独立的过滤或映射创建,因此时间列和值列不再描述相同的观测。
检查
- 在调用图表之前比较每列的长度。
- 在传输缓冲区之前验证数值转换。
修复
- 先对完整源观测值进行过滤和排序,然后将它们拆分为对齐的类型化列。
- 仅在文档化的折线序列间隙使用显式 NaN;OHLCV 值必须保持为有效的蜡烛数据。
在传输前拒绝未对齐的列
const lengths = [timestamp.length, open.length, high.length, low.length, close.length, volume.length];
if (!lengths.every((length) => length === lengths[0])) {
throw new RangeError(`OHLCV columns are misaligned: ${lengths.join(", ")}`);
}SSR 或水合访问仅浏览器可用的图表 API
适用于:line,stock。
症状。 服务器渲染抛出错误,原因是 window、document、Worker 或 HTMLCanvasElement 不可用,或水合产生不同的 DOM 树。
可能原因。 交互式浏览器图表在服务器评估期间构造,而不是在客户端挂载后构造。
检查
- 查找在模块范围或服务器组件内部的图表构造。
- 通过 @sixtyfold/ssr 将服务器图像生成与浏览器交互分离。
修复
- 在客户端拥有的组件内使用官方框架适配器。
- 在 SSR 期间渲染稳定宿主,仅在挂载后初始化交互式图表。
将 Next.js 图表保留在客户端边界之后
"use client";
import type { MultiSeriesData, TimeSeriesData } from "@sixtyfold/core";
import { SixtyfoldLineChart } from "@sixtyfold/react/line";
type LineData = TimeSeriesData | MultiSeriesData;
export function ChartPanel({ data }: { data: LineData }) {
return <SixtyfoldLineChart data={data} options={{ renderMode: "auto" }} />;
}Worker 或内存在导航后仍然存在
适用于:line,stock。
症状。 在反复打开视图后内存增长,或导航后旧图表继续渲染。
可能原因。 原生图表或临时数据 Worker 在其所属视图被移除时未被销毁。
检查
- 在若干次 mount/unmount 循环前后记录浏览器堆快照。
- 查找被保留的图表实例、Worker、观察者或已解码的源数组。
修复
- 对每个原生图表实例恰好调用一次 destroy()。
- 在最终传输后终止临时 fetch/decode Worker;官方框架适配器会自动销毁图表 Worker。
释放图表和摄取(ingestion)Worker
return () => {
dataWorker?.terminate();
chart.destroy();
};交互变慢或丢帧
适用于:line,stock。
症状。 缩放、平移、初始解码或流更新明显阻塞或未达到目标帧率。
可能原因。 主线程正在解码或重塑过多数据,图表降级到回退渲染器,或可见工作负载包含目标设备无法维持的更多绘制传递。
检查
- 检查统计信息:renderMode、frameTime、可见工作量和交互序列期间的 LOD 就绪情况。
- 分别分析抓取、解码、转换、传输和渲染的性能剖面。
修复
- 使用 renderMode 自动模式,在专用数据 Worker 中准备列式类型化数组,进行一次传输,然后终止该摄取 Worker。
- 对具代表性的浏览器、DPR、序列数量和手势进行基准测试;60 FPS 是设计目标,而非与设备无关的保证。
测量活动渲染路径
chart.setStatsCallback((stats) => {
console.table({
mode: stats.renderMode,
fps: stats.fps,
frameTime: stats.frameTime,
ready: stats.lodReady,
});
}, { intervalMs: 250 });缩放稳定后线条细节突变
适用于:line。
症状。 视口平滑动画,但手势结束时线条纹理再次发生变化。
可能原因。 呈现密度或网格重基线对工作负载过于激进,或应用代码在动画结束后替换了数据或外观。
检查
- 在观察呈现密度、网格增量和查询访问的同时重放相同的视口序列。
- 检查应用端是否在动画稳定后调用了 setData()、setAppearance() 或恢复视口。
修复
- 从自适应模式开始,密度设为 0.75,rebaseRatio 设为 1.25,quantizationStep 设为 0.25。
- 使用 setLODOptions() 一次调整一个系数;对于开销大的范围填充或异常大的多序列工作,使用密度 0.25。
在不重建图表的情况下调整呈现
chart.setLODOptions({
mode: "adaptive",
density: 0.75,
rebaseRatio: 1.25,
quantizationStep: 0.25,
});折线跨越缺失观测点相连
适用于:line。
症状。 折线在没有测量值的区间上视觉上穿过。
可能原因。 缺失观测被删除或被替换为零,而不是表示为对齐的 NaN 间隙。
检查
- 当需要可见断裂时,确认共享的 X 列包含该缺失区间。
- 检查摄取过程是否将 null 值转换为零。
修复
- 保持对齐的 X 位置,并将缺失的折线值编码为 Number.NaN。
- 不要合成 OHLCV 蜡烛或连接市场休市;股票时间尺度行为由观测到的蜡烛驱动。
表示真实的折线序列间隙
const data = {
x: new Float64Array([0, 1, 2, 3]),
y: new Float64Array([12, Number.NaN, Number.NaN, 18]),
length: 4,
};