资讯动态

Chart.js 渐进式折线动画:用逐点延迟与脚本化起止值实现“描线生长“效果

发布时间:2026/9/18 2:52:59 来源:尧图企业网站定制
Chart.js 渐进式折线动画用逐点延迟与脚本化起止值实现描线生长效果【免费下载链接】Chart.jsSimple HTML5 Charts using thetag项目地址: https://gitcode.com/gh_mirrors/ch/Chart.jsChart.js 的动画系统支持对元素属性的插值、延迟与脚本化起止值进行精细控制。本文以官方示例 progressive-line.md 为骨架完整解析如何让 1000 个数据点沿着折线逐点生长progressive line并深入其背后的核心源码机制帮助你掌握delay、from脚本化起止值与插值器的配合方法并将其复用到实时监控、数据流回放等场景。读完后你将能自己写出进度条式绘制打字机式数据回放等一流动画。示例全景1000 个数据点的逐点生长该示例生成两条随机游走数据集各 1000 个点通过配置animation.x与animation.y两个属性级动画让折线从左到右、从下到上逐点延伸形成描线生长的视觉效果。数据准备{x, y} 对象数组示例使用线性 x 轴type: linear数据以{x, y}对象数组形式提供。通过循环生成两条近似随机游走的数据const data []; const data2 []; let prev 100; let prev2 80; for (let i 0; i 1000; i) { prev 5 - Math.random() * 10; data.push({x: i, y: prev}); prev2 5 - Math.random() * 10; data2.push({x: i, y: prev2}); }{x: i, y: prev}是折线图的标准内部数据格式参见 docs/charts/line.md 的 Internal data format 一节。两条数据集通过borderColor区分红/蓝borderWidth: 1radius: 0隐藏数据点聚焦于线条本身。核心动画配置逐行拆解总时长与单点间隔const totalDuration 10000; // 总动画时长 10 秒 const delayBetweenPoints totalDuration / data.length; // 每点间隔 10msdelayBetweenPoints是整个逐点效果的时间基准每个点在其前一个点开始动画的delayBetweenPoints毫秒之后启动。脚本化起始值 previousYconst previousY (ctx) ctx.index 0 ? ctx.chart.scales.y.getPixelForValue(100) : ctx.chart.getDatasetMeta(ctx.datasetIndex).data[ctx.index - 1].getProps([y], true).y;这是整个示例最精妙的部分——from可以是脚本化函数函数接收context对象第一个点ctx.index 0从 y 轴刻度位置getPixelForValue(100)对应的像素值开始即从基准线 100 出发。后续点通过ctx.chart.getDatasetMeta(ctx.datasetIndex)拿到当前数据集的元信息meta.data是已解析的元素数组源码见 src/core/core.controller.js再取前一个点元素getProps([y], true)的当前动画值y像素坐标。这样每个点都从前一个点的当前位置出发保证线条是连续的、逐点连接的。注意getProps([y], true)的第二个参数为true表示取动画过程中的当前值而非目标值。这正是追线效果的关键——后一个点跟随前一个点的实时位置。animation.x横向逐点推进x: { type: number, easing: linear, duration: delayBetweenPoints, from: NaN, // 初始被跳过 delay(ctx) { if (ctx.type ! data || ctx.xStarted) return 0; ctx.xStarted true; return ctx.index * delayBetweenPoints; } }type: number指定数字插值器from (to - from) * factor见 src/core/core.animation.js 的interpolators.number。easing: linear保证匀速推进。duration等于单点间隔每个点只花一个间隔的时长完成位移。from: NaN是先不画的技巧NaN 作为起始值会让该点初始不可见tick()中factor为 NaN 时插值结果仍为 NaNCanvas 绘制 NaN 坐标即跳过从而让点等待其delay结束才出现。delay(ctx)脚本化延迟通过ctx.type ! data过滤非数据上下文利用ctx.xStarted标志位保证每个点只被触发一次ctx对象在动画期间被复用详见 docs/general/options.md 的 Option Context 说明延迟量 ctx.index * delayBetweenPoints实现第 N 个点在第 N 个间隔后启动。animation.y纵向跟随前点y: { type: number, easing: linear, duration: delayBetweenPoints, from: previousY, // 脚本化起始值 delay(ctx) { if (ctx.type ! data || ctx.yStarted) return 0; ctx.yStarted true; return ctx.index * delayBetweenPoints; } }与x几乎相同唯一区别是from使用上面定义的previousY脚本化函数。y 的动画跟随前一点的实时 y 像素值于是每个新点总是从前一个点的当前位置出发形成平滑的连续描线。完整可运行配置const config { type: line, data: { datasets: [ { borderColor: Utils.CHART_COLORS.red, borderWidth: 1, radius: 0, data: data }, { borderColor: Utils.CHART_COLORS.blue, borderWidth: 1, radius: 0, data: data2 } ] }, options: { animation, // 上面定义的 animation 对象 interaction: { intersect: false }, plugins: { legend: false }, scales: { x: { type: linear } } } };interaction: { intersect: false }关闭命中检测鼠标悬停时按最近点响应避免干扰动画。plugins: { legend: false }隐藏图例。scales.x.type: linear数值轴才能与{x: i}的数值坐标配合。源码级原理动画配置如何生效配置解析与默认值动画相关配置有三层animation全局、animations按属性、transitions按模式可配置在图表options、datasets[type]、overrides[type]下详见 docs/configuration/animations.md。默认值定义在 src/core/core.animations.defaults.jsanimation默认duration: 1000、easing: easeOutQuart、delay: undefined、loop: undefined、from/to/fn/type: undefined。animations预置两套numbers属性[x,y,borderWidth,radius,tension]类型number与colors属性[color,borderColor,backgroundColor]类型color。示例中自定义的x/y配置会覆盖numbers的对应属性。属性解析与动画创建Animations.configuresrc/core/core.animations.js把配置中的每个 key 解析为{duration, easing, delay, loop, from, to, fn, type}集合绑定到具体属性名。_createAnimations对每个发生变化的属性若已有活跃动画则更新to与剩余时长若cfg.duration为空则直接赋值不动画否则创建Animation实例并交给全局单例Animator。动画执行循环Animator._updatesrc/core/core.animator.js通过requestAnimationFrame循环驱动对每个活跃Animation调用tick(date)当elapsed 0还没到delay结束时tick()将属性保持为from值——这正是delay期间点停留在起点/被跳过的实现机制。tick()的核心逻辑factor (elapsed / duration) % 2; factor loop factor 1 ? 2 - factor : factor; factor this._easing(Math.min(1, Math.max(0, factor))); this._target[prop] this._fn(from, to, factor);即先由delay决定起始时刻再由easing函数把归一化时间映射为进度因子最后用插值器fn计算属性值。脚本化选项与上下文from、delay等字段均为脚本化选项Scriptable Options会被以context为参数调用。context.type data表示当前处于数据级上下文此时context还包含dataIndex、datasetIndex、parsed、raw、element等字段见 docs/general/options.md。示例正是利用ctx.index即dataIndex来计算逐点延迟。注意_scriptable白名单src/core/core.animations.defaults.js允许除onProgress、onComplete、fn外的所有 animation 字段脚本化。交互相关 API示例用到的两个 APIChart.getDatasetMeta(datasetIndex)返回某数据集的元信息对象其data数组是按顺序排列的元素点、弧、条等见 src/core/core.controller.js。Scale.getPixelForValue(value)把数据值换算为画布像素坐标线性轴实现见 src/scales/scale.linear.js基类默认返回NaN由各轴覆盖坐标原点在画布左上角。扩展与常见问题复用技巧调整速度修改totalDuration如改为 5000 即 5 秒完成全部描线。数据量自适应delayBetweenPoints totalDuration / data.length让延迟自动适配点数数据越多每个点越快。只做横向推进若只想要从左到右展开各点同时纵向到位可将animation.y的from保留为当前值不设脚本化起始仅保留x的延迟。配合 transitions可将此动画放入transitions的某自定义mode中通过chart.update(mode)触发见 docs/developers/api.md 的 update(mode) 说明。常见坑from: NaN的语义NaN 起始值使点在延迟前不可见但若同时需要点在延迟前显示于某固定位置则应改用from: 像素值。ctx标志位的必要性delay回调在动画每帧都可能被调用必须用ctx.xStarted/ctx.yStarted之类标志保证延迟只计算一次否则延迟会累加或重复触发。getProps第二参数务必传true取动画实时值否则拿到的是目标值线条会出现跳变。参考文档动画配置总览animation/animations/transitions三层结构、easing 全表、onProgress/onComplete回调延迟动画示例另一个delay脚本化用法柱状图逐列错峰出现折线图文档数据集属性、数据格式选项解析与脚本化选项Option Context 各级上下文字段Chart APIgetDatasetMeta 与 Scale APIgetPixelForValue【免费下载链接】Chart.jsSimple HTML5 Charts using thetag项目地址: https://gitcode.com/gh_mirrors/ch/Chart.js创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价