Chart.js 数据降采样(Data Decimation)插件完全指南:LTTB 与 Min/Max 算法配置与源码原理
Chart.js 数据降采样Data Decimation插件完全指南LTTB 与 Min/Max 算法配置与源码原理【免费下载链接】Chart.jsSimple HTML5 Charts using thetag项目地址: https://gitcode.com/gh_mirrors/ch/Chart.js导读本指南深入解析 Chart.js 内置的 decimation数据降采样插件——它专为**大数据量折线图line chart**设计可在图表生命周期起始阶段自动削减渲染点数从而显著提升绘制性能与交互流畅度。文章将完整覆盖插件的全部配置项、两种内置算法LTTB 与 Min/Max的适用场景、六项启用前置要求并结合仓库源码src/plugins/plugin.decimation.js与测试用例讲透降采样在何时触发、如何降、如何还原三环节的底层实现。读完你将能直接复用一个基于 10 万数据点的完整示例配置并理解在何种数据特征下应选择哪种算法。为什么需要数据降采样折线图的数据点一旦达到数万甚至十万级别Canvas 渲染和事件命中检测都会成为明显的性能瓶颈。decimation 插件的思路很直接在图表生命周期早期元素更新之前就把原始数据替换为一份精简后的数据子集让后续的解析、布局、绘制与交互都只面对少量点。该插件定义于 src/plugins/plugin.decimation.js插件 id 为decimation可通过 官方示例 直观感受默认不降采样与启用降采样后同一份 10 万点数据的渲染差异。需要强调的是decimation 与 decimation 之外的其他性能手段 不同它是有损压缩——通过牺牲部分数据细节换取渲染性能因此必须按数据类型与业务诉求权衡算法。该插件默认关闭enabled: false需要显式开启。配置选项插件的配置命名空间为options.plugins.decimation全局默认值定义于Chart.defaults.plugins.decimation。源码中插件对象的defaults字段plugin.decimation.js即承载了这些默认值。名称类型默认值描述enabledbooleanfalse是否启用降采样。注意插件默认关闭需显式开启algorithmstringmin-max使用的降采样算法可选lttb或min-max详见下文算法章节samplesnumber无仅当使用lttb算法时生效表示输出数据集中的采样点数量。默认取 canvas 宽度即每像素 1 个样本点thresholdnumber无当当前轴可见范围内的样本数大于该值时触发降采样。默认取 4 倍 canvas 宽度。注意降采样后的点数可能仍高于threshold值源码中与默认值/阈值直接相关的逻辑如下plugin.decimation.jsconst threshold options.threshold || 4 * availableWidth; if (count threshold) { // No decimation is required until we are above this threshold cleanDecimatedDataset(dataset); return; }其中availableWidth即chart.widthplugin.decimation.js。也就是说只有当可见数据点数超过 4 倍画布宽度时降采样才会被真正触发低于阈值时插件会静默跳过并顺带清理可能残留的旧降采样状态。动态切换算法与启用状态插件的三个核心配置都可以在运行时通过chart.options.plugins.decimation.xxx修改并调用chart.update()生效。官方示例data-decimation.md提供了四种可交互切换的状态// 关闭默认 chart.options.plugins.decimation.enabled false; chart.update(); // min-max 算法 chart.options.plugins.decimation.algorithm min-max; chart.options.plugins.decimation.enabled true; chart.update(); // LTTB 算法50 个采样点 chart.options.plugins.decimation.algorithm lttb; chart.options.plugins.decimation.enabled true; chart.options.plugins.decimation.samples 50; chart.update(); // LTTB 算法500 个采样点 chart.options.plugins.decimation.algorithm lttb; chart.options.plugins.decimation.enabled true; chart.options.plugins.decimation.samples 500; chart.update();enabled从true切回false时插件会通过cleanDecimatedData(chart)遍历所有数据集、移除_decimated与_data并恢复原始data属性详见下文数据还原机制因此来回切换是安全的。降采样算法原理与适用场景插件支持两种算法通过algorithm选项选择。若传入不支持的算法名插件会直接抛出Unsupported decimation algorithm xxx错误plugin.decimation.js这也意味着算法名必须严格匹配lttb或min-max。Largest Triangle Three BucketsLTTB降采样LTTB 算法能够在保留数据整体趋势的前提下将数据点数量压缩到非常少特别适合用少量点看趋势的场景例如长期监控曲线的宏观形态。其实现位于 plugin.decimation.js注释明确指出该实现基于 Sveinn Steinarsson 的 flot-downsample 项目MIT 许可。核心思路先把数据在 x 轴上大致均分为若干个桶bucket再从每个桶中挑选出能与相邻两点构成最大三角形面积的点作为代表点从而保证被选中的点是最能凸显形状的拐点。算法始终保留首点与末点const samples options.samples || availableWidth; // 如果采样数不小于数据量直接返回原始切片 if (samples count) { return data.slice(start, start count); } ... decimated[sampledIndex] data[a]; // 首点 for (i 0; i samples - 2; i) { // 计算每个桶的平均点再在与相邻点构成的三角形中找面积最大者 ... decimated[sampledIndex] maxAreaPoint; ... } decimated[sampledIndex] data[endIndex]; // 末点其中samples的取值逻辑印证了文档说法未显式指定samples时默认取availableWidthcanvas 宽度即每像素 1 个样本点。文档中的samples描述、默认行为与源码完全一致。一个值得注意的实现细节原版算法将maxArea初始化为 1而本仓库改为初始化为-1。源码注释解释了原因——三角形面积恒为非负在数据为水平直线面积恒为 0时若初始值为 1 会导致nextA永不被赋值下一轮循环中a变成undefined而崩溃。这一修复也由测试用例should not crash with uneven pointstest/specs/plugin.decimation.tests.js覆盖该用例用 15552 个不均匀点验证了不抛异常。Min/Max 降采样Min/Max 算法保留数据的峰值与谷值是极值保持型算法非常适合噪声大、必须看到尖峰信号的时序数据如振动、脉冲类监测数据。其实现位于 plugin.decimation.js。核心思路将可见数据按 x 像素坐标映射并分组同一像素列内的点只保留 y 值最小和最大的两个点连同组首、组尾点一起输出从而保证每个像素列上极值不丢失。源码注释明确说明每个区间最多输出 4 个点组首、min、max、组尾if (truncX prevX) { // 同一像素列内维护 minY / maxY 及对应下标 ... } else { // Push up to 4 points, 3 for the last interval and the first point for this interval const intermediateIndex1 Math.min(minIndex, maxIndex); const intermediateIndex2 Math.max(minIndex, maxIndex); ... decimated.push(point); // 新区间的起点 }这也是文档所述Min/Max 每个像素最多需要 4 个点的由来。对比而言LTTB输出点数由samples严格控制压缩率最高适合看趋势Min/Max输出点数随像素宽度浮动最多每像素 4 点保真度更高适合看极值/噪声信号。六项启用前置要求逐一对应源码验证文档明确指出启用该插件前必须满足以下全部要求。这些要求并非文档空谈每一条都能在插件源码的beforeElementsUpdate钩子中找到对应的守卫判断plugin.decimation.js数据集的indexAxis必须为x源码中resolve([indexAxis, chart.options.indexAxis]) y时直接跳过L220-L223。即不支持横向y 轴索引折线图文档对应链接见 line.md 的 General 章节。数据集必须是折线line数据集源码检查meta.controller.supportsDecimationL225。supportsDecimation默认在基类 core.datasetController.js 中为false仅在 controller.line.js以及 scatter 控制器中被置为true。因此 bar、doughnut 等图表类型天然不适用。X 轴必须为linear或time类型源码检查xAxis.type ! linear xAxis.type ! timeL230-L234。category等离散轴不支持相关轴文档见 linear 轴 与 time 轴。数据必须无需解析即parsing必须为false源码检查chart.options.parsing为真则跳过L236-L239。原因在于降采样算法直接以{x, y}对象形式读写数据如data[j].x、data[j].y需要数据已是解析后的内部格式。相关说明见>dataset._data data; // 原始数据存入 _data delete dataset.data; Object.defineProperty(dataset, data, { configurable: true, enumerable: true, get: function() { return this._decimated; }, // 读操作返回降采样结果 set: function(d) { this._data d; } // 写操作仍写回原始数据 });之后 Chart.js 内部及用户读取dataset.data时拿到的都是降采样后的_decimated而用户若给dataset.data赋新值会被 setter 存入_data下次更新时重新降采样。需要还原时cleanDecimatedDatasetL156-L168会删除_decimated、_data并将data重新定义为普通可写属性、恢复原始数据。该清理逻辑在插件destroy钩子L284-L286中也会执行避免图表销毁后留下悬挂引用。此外_decimated标记还会传递给折线元素折线控制器会把line._decimated !!_dataset._decimated写入元素controller.line.js而 element.line.js 的绘制快速路径useFastPath会跳过降采样数据上的复杂插值计算进一步提升渲染性能。完整可运行示例10 万数据点的降采样配置官方示例docs/samples/advanced/data-decimation.md给出了一个完整的、可直接运行的 10 万点折线图配置。它以 30 秒为间隔生成从2021-04-01T00:00:00Z开始的 10 万个{x, y}时间序列点其中绝大多数数据落在[0, 20)约 0.1% 的罕见数据落在[0, 100)——这种罕见尖峰分布恰好能体现两种算法的差异const NUM_POINTS 100000; Utils.srand(10); const start Utils.parseISODate(2021-04-01T00:00:00Z).toMillis(); const pointData []; for (let i 0; i NUM_POINTS; i) { const max Math.random() 0.001 ? 100 : 20; pointData.push({x: start (i * 30000), y: Utils.rand(0, max)}); } const decimation { enabled: false, // 先关闭示例中通过 actions 动态切换 algorithm: min-max, }; const config { type: line, data: { datasets: [{ borderColor: Utils.CHART_COLORS.red, borderWidth: 1, data: pointData, label: Large Dataset, radius: 0, }] }, options: { // 关闭动画与数据解析以获得最佳性能 animation: false, parsing: false, // 必须为 false否则插件跳过 interaction: { mode: nearest, axis: x, intersect: false }, plugins: { decimation: decimation, }, scales: { x: { type: time, // 必须为 time 或 linear ticks: { source: auto, maxRotation: 0, // 关闭刻度旋转提升性能 autoSkip: true, } } } } };该配置满足全部前置要求type: line、x 轴为time、parsing: false、数据为预解析的{x, y}对象数组且按 x 升序。示例内置的 actions 面板支持在不降采样 / min-max / LTTB(50) / LTTB(500)四种状态间切换用于对比压缩率与形态保真度。运行时动态切换的代码见上文动态切换算法与启用状态一节。测试验证算法行为的关键断言仓库测试test/specs/plugin.decimation.tests.js从多个角度锁定了插件行为可作为配置预期的重要参考采样数上限保护samples: 100大于 10 个数据点时输出仍为全部 10 个点should draw all element if sample is greater than data based on canvas width采样数精确控制samples: 7时输出恰好 7 个点should draw the specified number of elements based on canvas width阈值门槛samples: 5, threshold: 7时输出 5 个点证明阈值只决定是否触发而非输出多少should draw the specified number of elements based on threshold可见范围裁剪x 轴范围限定为 3–6 时输出仅覆盖该范围含范围前一点与范围内各点的 5 个点should draw all element only in range佐证降采样只在可见区间内进行边界健壮性15552 个不均匀点在devicePixelRatio: 1.25下不抛异常should not crash with uneven points对应 LTTB 实现中maxArea初始化的修复。这些断言与文档参数表、源码逻辑互相印证samples决定 LTTB 输出规模threshold决定是否触发可见范围决定处理的数据窗口。实践建议与注意事项数据必须预排序由于parsing: false时数据需为内部格式且按 x 升序见>【免费下载链接】Chart.jsSimple HTML5 Charts using thetag项目地址: https://gitcode.com/gh_mirrors/ch/Chart.js创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

DevOps 看 Google Home MCP,Token 消耗用 TaoToken

DevOps 看 Google Home MCP,Token 消耗用 TaoToken

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/20 2:12:48 阅读更多 →
金融审批数仓:累积快照建模实战指南

金融审批数仓:累积快照建模实战指南

简介:本资源是一份面向大数据工程师、数据仓库开发者及金融行业数据分析人员的系统性学习文档,聚焦数据仓库架构设计、建模方法论与金融审批场景落地实践。内容覆盖Dolphin Scheduler、Hive、ODS/DWD/DIM/DWS/ADS分层模型、MaxwellFlume数据采集链路&…

2026/9/21 1:01:08 阅读更多 →
通达OA任意文件上传叠加文件包含导致RCE的链路与加固

通达OA任意文件上传叠加文件包含导致RCE的链路与加固

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/21 4:06:54 阅读更多 →

最新新闻

3分钟搞定以太坊区块中文浏览器,附完整示例

3分钟搞定以太坊区块中文浏览器,附完整示例

3分钟搞定以太坊区块中文浏览器,附完整示例 你是不是也遇到过这种情况:Python语法背得滚瓜烂熟,LeetCode题也能刷几道,但一旦要动手搭个实际项目,脑子就一片空白?尤其是面对区块链这种看似高大上的领域,连个区块数据都看不明白,更别提…

2026/9/22 4:50:07 阅读更多 →
3个坑让你手写实现阿里家家逻辑更稳

3个坑让你手写实现阿里家家逻辑更稳

3个坑让你手写实现阿里家家逻辑更稳 Stack Trace 滚了一屏,满屏的 NullPointerException 和 IndexOutOfBoundsException…

2026/9/22 4:50:07 阅读更多 →
3步搞定翻译英文网站:新手避坑指南与实战代码

3步搞定翻译英文网站:新手避坑指南与实战代码

3步搞定翻译英文网站:新手避坑指南与实战代码 复制来的翻译代码跑不通,报错信息满屏飞,到底哪里出了问题?别慌,这是绝大多数初学者在尝试 翻译英文网站…

2026/9/22 4:50:07 阅读更多 →
动作类网页游戏开发3个最佳实践破解语法落地难题

动作类网页游戏开发3个最佳实践破解语法落地难题

动作类网页游戏开发3个最佳实践破解语法落地难题 刚跑通 Hello World 就卡壳?学会语法却不知怎么搭项目,是动作类网页游戏开发中最常见的陷阱。很多初学者盯着教程敲完所有代码,关掉编辑器后面对空白新建文件,脑子一片空白。这种“会写不会…

2026/9/22 4:50:07 阅读更多 →
北京健康宝出现弹窗怎么恢复绿码:3步搞定前端状态同步高频面试题

北京健康宝出现弹窗怎么恢复绿码:3步搞定前端状态同步高频面试题

北京健康宝出现弹窗怎么恢复绿码:3步搞定前端状态同步高频面试题 配置环境就卡半天?别急,这往往不是网络问题,而是前端状态管理在作祟。很多人遇到“北京健康宝出现弹窗怎么恢复绿码”的情况,以为只是数据延迟,其实这是典型的 高频面试题…

2026/9/22 4:50:07 阅读更多 →
转换生成语法避坑速查手册:3招搞定复制代码报错

转换生成语法避坑速查手册:3招搞定复制代码报错

转换生成语法避坑速查手册:3招搞定复制代码报错 刚复制完网上那段“转换生成语法”的代码,回车一敲,控制台直接飘红。是不是心里瞬间凉半截?明明看着逻辑挺顺,变量名也没拼错,怎么就是跑不通?这种“看代码像看天书,调Bug像拆炸弹”的绝望感,每个…

2026/9/22 4:49:07 阅读更多 →

日新闻

3台商务办公笔记本实测:手写实现环境配置,告别卡半天

3台商务办公笔记本实测:手写实现环境配置,告别卡半天

3台商务办公笔记本实测:手写实现环境配置,告别卡半天 配置环境就卡半天?别怪机器慢,多半是你没选对工具链。在Java、Go或Python的项目现场, 手写实现…

2026/9/22 0:00:41 阅读更多 →
剑帝加点速查手册:3分钟搞懂核心逻辑

剑帝加点速查手册:3分钟搞懂核心逻辑

剑帝加点速查手册:3分钟搞懂核心逻辑 面试被问原理答不上来,是不是常态?别慌。很多开发者对着 GitHub 开源仓库里的代码发呆,看似简单实则暗藏玄机。今天这份【剑帝加点】速查手册,直接带你拆解核心实现,把面试必考的原理讲透。…

2026/9/22 0:00:41 阅读更多 →
手写实现图片压缩网站核心:搞定WebP转换与质量调优

手写实现图片压缩网站核心:搞定WebP转换与质量调优

手写实现图片压缩网站核心:搞定WebP转换与质量调优 复制来的代码跑不通不知道怎么调?别慌,这种“复制粘贴地狱”在开发圈太常见了。尤其是做 图片压缩网站…

2026/9/22 0:00:41 阅读更多 →

周新闻

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

直接铺开项目本身吧。这几个月我一直在折腾一件事:用Flutter给OpenHarmony做一款游戏集合类的App,说白了就是把若干小游戏塞进一个壳里,用统一入口分发。这个方向本身不算新鲜,真正让我花了不少心思的,是首页那堆游戏卡…

2026/9/22 4:32:41 阅读更多 →
Word表格编号全攻略:从列表编号到题注交叉引用

Word表格编号全攻略:从列表编号到题注交叉引用

写Word文档,最让人头疼的往往是那些“看起来不起眼”的小问题。比如表格编号这事:今天在表后面多加了两个空白行,明天给客户交稿前发现整个章节的编号全部错位,光是挨个改序号就能耗掉大半个下午。我前阵子帮人整理一份上百页的技…

2026/9/22 4:38:57 阅读更多 →
从第一个站到第二个站:独立开发者的静态网站选型与落地实践

从第一个站到第二个站:独立开发者的静态网站选型与落地实践

1. 项目概述1.1 核心需求解析做独立开发者这几年,说实话,第一个网站上线的那天晚上我兴奋得没睡着。但等它跑了半年,流量惨淡、功能臃肿、代码自己都懒得看第二遍之后,我才慢慢琢磨明白一个道理:第一个网站是练手&…

2026/9/21 4:51:05 阅读更多 →

月新闻

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

2026/9/21 15:36:51 阅读更多 →
容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…

2026/9/21 15:36:51 阅读更多 →
容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步分类:[工程技术]细分主题:Docker 容器化技术与镜像安全管理:核心链路的逐步实现与关键代码取舍面对一个积累了五六年历史包袱的单体架构应用(包含 Web 接口、后台…

2026/9/22 2:43:42 阅读更多 →