
数据可视化前端【免费下载链接】F2An elegant, interactive and flexible charting library for mobile.项目地址https://gitcode.com/gh_mirrors/f2/F2点击查看免费下载本文以 F2 仓库中antv/f2-algorithm子包的 CHANGELOG.md 为发展脉络结合其 源码、测试用例 与 README系统讲解该算法包提供的两类数据降采样能力——rateDownSample常见统计采样与lttbDownSample最大三角形三分桶采样覆盖参数配置、源码级实现原理、边界条件处理以及在 F2 折线图中的接入方式。读完本文你将能理解两种采样算法的取舍差异掌握在移动端图表中为大体积时序数据做降采样、保持图表形态与性能平衡的完整方案。一、f2-algorithm 在 F2 生态中的定位antv/f2-algorithm是 F2 移动端图表库的算法扩展包其 package.json 中的描述为 F2 algorithm extension关键词包含chart、mobile、visualization、sample等sideEffects声明为false便于按需打包。它并不依赖 F2 主包本身而是独立提供可复用的数据处理算法再与 F2 的Chart/Line组件组合使用。该包的入口文件 src/index.ts 非常精简只做一件事——导出两个降采样函数import lttbDownSample from ./lttbDownSample; import rateDownSample from ./rateDownSample; export { lttbDownSample, rateDownSample };也就是说整个算法包的能力收敛为两个 APIAPI算法类型适用场景rateDownSample常见统计采样nearest / max / min快速减点追求性能与简单可控lttbDownSampleLargest Triangle Three Buckets高质量保留趋势与波动形态适合视觉还原度要求高的场景从 CHANGELOG.md 的版本记录看该包经历了从命名、依赖配置到采样函数本身的多次修复本节后文的版本演进部分会结合这些记录展开。二、rateDownSample常见统计采样2.1 函数签名与参数说明rateDownSample定义在 src/rateDownSample.ts其核心参数通过OptionsProps声明export interface OptionsProps { sampling: nearest | max | min | Function; /* 周期 */ rate: number; dimension: string; }参数类型默认值含义samplingnearest \| max \| min \| Functionnearest采样策略也支持传入自定义函数ratenumber5采样周期/抽稀比例含义是每隔 rate 个点取 1 个代表点dimensionstringvalue参与极值比较的数值字段名例如折线图的 y 轴字段函数入口处的默认值解构与前置校验是理解其行为的关键rateDownSample.ts#L63-L75export default function rateDownSample(data, options?: OptionsProps) { const { sampling nearest, rate 5, dimension value } options; let sampler; if (isFinite(rate) rate 1) { if (isString(sampling)) { sampler samplers[sampling]; } else if (isFunction(sampling)) { sampler sampling; } return downSample(data, rate, sampler, dimension); } return data; }两个关键约束rate必须是大于 1 的有限数否则函数直接原样返回data不做任何采样sampling既支持内置字符串也支持传入自定义函数扩展性强。2.2 分帧采样核心downSampledownSamplerateDownSample.ts#L11-L31是rateDownSample的内部实现逻辑非常直观——按frameSize Math.floor(rate)将数据切成若干帧bucket每帧内调用一次sampler取一个代表点function downSample(data, rate, sampler, dimension) { const sampled []; let sampledIndex 0; const len data.length; let frameSize Math.floor(rate); for (let i 0; i len; i frameSize) { // Last frame frameSize frameSize len - i ? len - i : frameSize; const frameValues []; for (let k 0; k frameSize; k) { frameValues[k] data[k i]; } const value sampler(frameValues, dimension); sampled[sampledIndex] value; } return sampled; }值得注意的细节最后一帧的长度会自动截断frameSize frameSize len - i ? len - i : frameSize保证采样过程不会越界或丢失尾部数据这一点正是 CHANGELOG 中相关边界问题修复所覆盖的场景。2.3 内置采样器nearest / max / min内置采样器定义在 rateDownSample.ts#L33-L54const samplers { max: (frame, dimension) { const max -Infinity; let maxData; for (let i 0; i frame.length; i) { frame[i][dimension] max (maxData frame[i]); } return maxData || NaN; }, min: (frame, dimension) { const min Infinity; let minData; for (let i 0; i frame.length; i) { frame[i][dimension] min (minData frame[i]); } return minData || NaN; }, // TODO 中位数 median nearest: (frame) { return frame[0]; }, };nearest最近邻直接取每帧的第一个数据点。实现最廉价、速度最快但如测试快照所示会大幅丢失局部波动细节曲线形态最粗糙。max/min极值采样在每帧内按dimension字段找出最大值/最小值对应的整条数据记录并返回。适合需要保留峰值/谷值语义的场景例如股票 K 线、波峰波谷监测。需要注意的是如果帧内没有满足比较条件的数据可能返回NaN源码中的return maxData || NaN。自定义函数sampling也接受Function签名约定为(frameValues, dimension) value可以从帧内按业务规则挑选代表点。源码中// TODO 中位数 median的注释表明中位数采样是一个计划中的扩展方向目前尚未实现。三、lttbDownSample最大三角形三分桶LTTB采样3.1 LTTB 算法思想LTTBLargest Triangle Three Buckets最大三角形三分桶是面向时序数据的高质量降采样算法。其核心思想是把数据等分为若干桶对每个桶用上一桶已选点 A、本桶候选点 B、下一桶平均点 C构造三角形保留面积最大的那个点——三角形面积越大说明该点对曲线形态的影响越关键从而在减点的同时最大限度保留主趋势、峰值与谷值位置。实现位于 src/lttbDownSample.ts参数接口同样为OptionsPropsrate与dimension默认值分别为5和value。3.2 前置边界条件export default function lttbDownSample(data, options?: OptionsProps) { const { rate 5, dimension value } options; const len data.length; const targetCount len / rate; if (rate len || targetCount 2) { return data; } ...lttbDownSample.ts#L17-L24LTTB 有两个明确的边界保护rate len采样比例大于等于数据量无需采样原样返回targetCount 2目标点数不足 2 个时算法无法成立至少需要首尾两个锚点原样返回。这两条正是 CHANGELOG 中5.0.34修复项data数量小于rate对应 issue #1880所解决的边界问题——当数据量小于rate时降采样不再报错或产生异常结果而是安全地回退为返回原始数据。3.3 算法主循环的源码解读主循环lttbDownSample.ts#L26-L81分四步计算桶大小bucketSize Math.floor((len - 2) / (targetCount - 2))因为首尾两点始终保留实际只需在中间挑选targetCount - 2个点。保留首点sampled[0] data[0]并将a 0作为初始锚点 A。逐桶挑选最大面积点对第 C 桶先求dimension字段的平均值得到平均点(avgX, avgY)然后在第 B 桶内遍历每个候选点计算点 A、候选点 B、平均点 C三点构成三角形的面积area Math.abs( (pointA_x - avgX) * (Number(data[rangeOffs][dimension]) - pointA_y) - (pointA_x - rangeOffs) * (avgY - pointA_y) ) * 0.5;面积最大者即被选中同时更新下一轮锚点a nextA。 4.保留末点循环结束后将data[len - 1]追加到结果尾部。从实现细节看dimension字段值会经Number()强转因此即使是字符串形式的数值数据如测试中的0.516也能被正确处理x 轴则默认按数据下标参与计算。整体上 LTTB 是保形优先的采样算法代价是比nearest更高的计算量——对每一桶都要遍历候选点计算三角形面积时间复杂度为O(n)但常数更大。四、在 F2 图表中的接入方式4.1 README 中的最小用法README.md 给出了最简接入示例先对数据做降采样再把采样结果交给Chart渲染import dataSample from antv/f2-algorithm; const sampleData dataSample({ data, sampling: nearest, rate: 7, }); Canvas pixelRatio{1} Chart data{sampleData} Line xdate yvalue / /Chart /Canvas;注意 README 示例使用的是包默认导出风格而实际 入口文件 导出的是具名的lttbDownSample与rateDownSample两个函数测试中也是按具名导入使用的见下文。实际接入时建议按具名方式导入例如import { lttbDownSample } from antv/f2-algorithm; const sampleData lttbDownSample(data, { rate: 7, dimension: value });4.2 测试用例中的完整接入链路test/sample.test.tsx 用 4 组用例演示了两类 API 与 F2 渲染管线的完整配合每个用例都通过createContext创建画布上下文、渲染后与快照做像素级比对origin data不采样直接渲染原始数据作为对照组lttb samplelttbDownSample(data, { rate: 7, dimension: value })后渲染rate 小于可抽个数构造 9 条数据、rate: 7的极端小样本场景验证边界保护逻辑nearest samplerateDownSample(data, { sampling: nearest, rate: 7, dimension: value })后渲染。测试数据取自远程 JSON字段date/valuevalue统一经Number()转换为数值后进入采样。这与真实业务中接口返回字符串数值、图表前先归一化的做法一致。对应的渲染快照存放于 test/image_snapshots从快照对比可以直观看到三种渲染结果的差异原始数据点最密集、锯齿感最强LTTB 减点后主趋势、峰值谷值位置与原始数据几乎一致仅抹掉细碎波动nearest 采样后数据最稀疏局部细节被大幅简化。五、从 CHANGELOG 看算法包的版本演进CHANGELOG.md 记录了该包自 5.0.31 以来的完整演进。由于 F2 采用 lerna monorepo 管理见根目录 lerna.json其 publish 配置启用了conventionalCommits大部分版本为纯版本对齐Note: Version bump only for package antv/f2-algorithm但其中有 4 次修复值得关注版本日期修复内容对应源码行为5.0.312023-09-05package name#1840包正式命名为antv/f2-algorithm5.0.342023-11-02data 数量小于 rate#1880lttbDownSample/rateDownSample增加边界回退数据量不足时原样返回5.5.02024-05-30algorithm package.json#1963修正包的依赖与发布配置antv/util、tslib等5.7.02024-10-09sample func#2004采样函数本身的缺陷修复结合 package.json 中当前版本5.7.0可以确认5.7.0 是当前仓库中该包的最新版本以上修复均已包含。这套CHANGELOG conventional commits lerna 版本对齐的流程也保证了每个历史问题都有据可查。从演进脉络中可以看到两个工程实践要点边界条件优先被修复data 数量小于 rate 这类边界问题在真实业务尤其是小样本或刚起步的数据源中极易触发因此两个采样函数都设计了参数不满足条件即原样返回的安全兜底算法包保持轻量独立多次修复集中在包命名、package.json 配置层面核心算法downSample分帧 samplers极值/最近邻 LTTB 三角形面积自 5.0.x 起即保持稳定说明其 API 设计与实现已收敛成熟。六、实战选型建议与参数速查6.1 两种采样如何选对趋势保真度要求高如金融行情、监控曲线、需要和原始数据看起来几乎一样的场景优先lttbDownSample它通过三角形面积最大化保留峰值、谷值与整体形态代价是略高的 CPU 开销追求极致性能、数据量极大且允许细节损失如日志曲线、大规模埋点展示优先rateDownSample的nearest采样常数时间取帧首点开销最小需要语义化极值如只看波峰波谷每帧保留最高点用rateDownSample的max/min采样配合dimension指定参与比较的数值字段。6.2 参数速查表参数默认值适用函数说明rate5两者采样比例。rateDownSample要求rate 1的有限数lttbDownSample要求rate len且len / rate 2否则原样返回dimensionvalue两者参与比较/计算的数值字段名源码会经Number()强转支持字符串数值samplingnearestrateDownSample独有nearest \| max \| min \| Function内置极值采样器按dimension找帧内最大/最小记录两个函数的通用调用模式import { lttbDownSample, rateDownSample } from antv/f2-algorithm; // 保形采样5000 点 → 约 714 点rate 7 const lttbData lttbDownSample(rawData, { rate: 7, dimension: value }); // 快速采样每帧取首个点 const nearestData rateDownSample(rawData, { sampling: nearest, rate: 7, dimension: value }); // 极值采样每帧保留 value 最大的记录 const maxData rateDownSample(rawData, { sampling: max, rate: 7, dimension: value });七、总结antv/f2-algorithm以两个函数覆盖了移动端图表最典型的降采样诉求rateDownSample提供快速、可定制的统计采样nearest / max / min / 自定义函数lttbDownSample提供高质量的保形采样。从 CHANGELOG.md 到 源码 再到 测试三者互相印证边界条件的兜底处理、默认参数的语义rate 5、dimension value、sampling nearest以及渲染快照的对比效果共同构成了一个开箱即用、行为可预期的算法扩展包。在实际项目中只需在渲染前对数据做一次降采样并传入Chart即可在大数据量场景下兼顾流畅渲染与形态还原。赞分享数据可视化前端【免费下载链接】F2An elegant, interactive and flexible charting library for mobile.项目地址https://gitcode.com/gh_mirrors/f2/F2点击查看免费下载相关推荐使用 antv/f2-algorithm 为 F2 移动端图表做高性能数据采样使用 antv/f2 algorithm 为 F2 移动端图表做高性能数据采样 数据采样down sampling / data sampling是移动端数据可视化前端F2 词云图扩展 antv/f2-wordcloud 实战指南从数据布局到遮罩形状定制F2 词云图扩展 antv/f2 wordcloud 实战指南从数据布局到遮罩形状定制 本篇指南围绕 F2 生态中的独立扩展包 antv/f2 wordc数据可视化前端3D点云降采样革命Open3D VoxelGrid算法原理与实战指南3D点云降采样革命Open3D VoxelGrid算法原理与实战指南 在3D点云处理中你是否遇到过这些痛点百万级点云导致算法运行缓慢复杂场景下的空间分析计算机视觉图形学3D渲染科学计算上一篇XposedRimetHelper钉钉助手远程打卡与位置模拟全解析下一篇corvu vs 其他SolidJS组件库为什么这款无样式UI原语能脱颖而出创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考