Chart.js 3.0 迁移指南:从 2.x 到 3.0 的完整破坏性变更解析与源码印证
Chart.js 3.0 是一次以“性能、可配置性与可维护性”为目标的重大版本升级。本文基于仓库中的 v3-migration.md 迁移指南展开,完整覆盖从 2.x 升级到 3.0 时需要修改的安装方式、图表类型、配置项、默认值、坐标轴、动画、交互与插件 API,并结合当前仓库(4.x 系列源码)中的核心实现——构造函数、注册表、默认值系统、动画器、交互模式与数据控制器——逐条印证这些变更在代码中的落点。读完后你可以完成:把一份 2.x 配置完整改写到 3.0+ 语法、理解 scales/defaults/interaction 新体系的组织方式,以及开发自定义控制器、插件时的 API 迁移路径。
v3.0 升级亮点
官方文档给出的 v3.0 主要变化可以概括为:
- 大幅的性能提升,包括可以跳过数据解析、通过 Web Workers 并行渲染图表,详见 性能优化;
- 更多的可配置项与 scriptable options,并改善了默认值;
- 完全重写的动画系统;
- 重写后的 filler 插件并修复了大量 bug;
- 文档从 GitBook 迁移到 VuePress;
- API 文档由 TypeDoc 生成和校验;
- 不再向页面注入 CSS;
- 大量 bug 修复;
- 支持 tree shaking(摇树优化)。
这些亮点并非营销口径,可以从当前仓库源码中找到对应实现,后文会给出文件级证据。
终端用户迁移
安装与入口
- 分发的文件名改为小写,例如
dist/chart.js。 - 不再提供
Chart.bundle.js与Chart.bundle.min.js。如果你之前使用 bundle 构建,请参考 安装 与 集成 文档中推荐的搭建方式。 moment不再是 npm 依赖。如果你使用time或timeseries刻度,必须自行引入一个可用的日期适配器(adapter)及对应日期库,构建时也不再需要排除 moment。- 当传入的 canvas/context 已被占用时,
Chart构造函数会直接抛出错误。 - Chart.js 3 支持 tree shaking。如果你以 npm 模块方式使用并希望利用该能力,需要自行 import 并注册要用的 controllers、elements、scales 和 plugins(可注册项清单见 集成)。通过
script标签引入或从auto注册路径以 npm 模块引入时不需要调用register,但也就享受不到摇树收益。
当前仓库中 package.json 的 dependencies 只有 @kurkle/color 一项,确认了 moment 已从依赖中移除;构建产物入口由 main/module/exports 字段声明(./dist/chart.cjs、./dist/chart.js、./auto/*、./helpers/*)。
构造函数复用画布会抛错这一点,可以在 core.controller.js 中直接看到:
constructor(item, userConfig) {
const config = this.config = new Config(userConfig);
const initialCanvas = getCanvas(item);
const existingChart = getChart(initialCanvas);
if (existingChart) {
throw new Error(
'Canvas is already in use. Chart with ID \'' + existingChart.id + '\'' +
' must be destroyed before the canvas with ID \'' + existingChart.canvas.id + '\' can be reused.'
);
}
// ...
}
tree shaking 与注册机制的入口在 src/index.ts:模块导出 controllers、elements、plugins、scales 四个命名空间,以及聚合了全部注册项的 registerables 数组;而 auto/auto.js 则代表“自动注册”路径——Chart.register(...registerables) 后再导出 Chart。
迁移指南中给出的注册示例(保留原样,可直接使用):
import { Chart, LineController, LineElement, PointElement, LinearScale, Title } from 'chart.js'
Chart.register(LineController, LineElement, PointElement, LinearScale, Title);
const chart = new Chart(ctx, {
type: 'line',
// data: ...
options: {
plugins: {
title: {
display: true,
text: 'Chart Title'
}
},
scales: {
x: {
type: 'linear'
},
y: {
type: 'linear'
}
}
}
})
Chart.register 的静态方法在 core.controller.js 中定义为对 registry.add 的转发,并刷新插件缓存(invalidatePlugins),这也是 Chart.plugins.register 被 Chart.register 取代的落点。
图表类型:horizontalBar 被移除
horizontalBar 图表类型被移除,横向柱状图改用新的 indexAxis 选项配置,详见 柱状图文档。
在源码中,indexAxis 是一个 chart 级选项:默认值在 core.defaults.js 中定义为 'x',而 controller.bar.js 通过 this.chart.options.indexAxis === 'x' ? dataset.xAxisID : dataset.yAxisID 来决定哪条轴是索引轴。因此迁移时只需把 type: 'horizontalBar' 的图表改为 type: 'bar' 并在 options 中设置 indexAxis: 'y'。
配置选项变更
通用变更
- 可索引(indexable)选项现在是循环的。例如
backgroundColor: ['red', 'green']在数据点超过 2 个时会按'red'/'green'交替取色。 - 对象型数据的输入属性名可以自由指定,详见 数据结构。
- 大多数选项现在通过 proxy 解析(resolver),而不是与默认值做合并。这既方便为不同上下文使用不同的解析路由,也允许在 scriptable options 中引用同一上下文里其他已解析的选项:
- 选项默认是 scriptable 且 indexable 的,除非因故被禁用;
- scriptable options 的第二个参数是一个 option resolver,用于访问同上下文的其他选项;
- 解析沿作用域向上回退(falls to upper scopes)。详见 options。
当前实现里,defaults.route()(core.defaults.js)用 getter/setter 实现了这种“路由回退”,而 core.defaults.js 末尾的 descriptors 声明了 _scriptable/_indexable 等描述符规则,例如 interaction 被标记为不可 scriptable、events 不可 indexable。
具体选项改名与移除
以下逐条对应迁移指南中的 “Specific changes”,建议直接按表改写配置:
| 2.x 写法 | 3.0 写法 / 说明 |
|---|---|
elements.rectangle |
elements.bar |
hover.animationDuration |
改为 animation.active.duration |
responsiveAnimationDuration |
改为 animation.resize.duration |
极坐标图 elements.arc.angle |
以“度”配置,不再是弧度 |
极坐标图 startAngle |
与 Radar 对齐:0 在正上方、单位为度;默认值由 -½π 改为 0 |
Doughnut rotation |
单位为度且 0 在正上方;默认值由 -½π 改为 0 |
Doughnut circumference |
单位为度;默认值由 2π 改为 360 |
Doughnut cutoutPercentage |
改名为 cutout,接受像素(数字)或以 % 结尾的字符串(百分比) |
scale 选项 |
移除,改用 options.scales.r(或任意 scale id,axis: 'r') |
scales.[x/y]Axes 数组 |
移除。scales 直接挂在 options.scales 对象上,以 scale id 为键 |
scales.[x/y]Axes.barPercentage |
移到数据集选项 barPercentage |
scales.[x/y]Axes.barThickness |
移到数据集选项 barThickness |
scales.[x/y]Axes.categoryPercentage |
移到数据集选项 categoryPercentage |
scales.[x/y]Axes.maxBarThickness |
移到数据集选项 maxBarThickness |
scales.[x/y]Axes.minBarLength |
移到数据集选项 minBarLength |
scales.[x/y]Axes.scaleLabel |
改名为 scales[id].title |
scales.[x/y]Axes.scaleLabel.labelString |
改名为 scales[id].title.text |
scales.[x/y]Axes.ticks.beginAtZero |
改名为 scales[id].beginAtZero |
scales.[x/y]Axes.ticks.max |
改名为 scales[id].max |
scales.[x/y]Axes.ticks.min |
改名为 scales[id].min |
scales.[x/y]Axes.ticks.reverse |
改名为 scales[id].reverse |
scales.[x/y]Axes.ticks.suggestedMax |
改名为 scales[id].suggestedMax |
scales.[x/y]Axes.ticks.suggestedMin |
改名为 scales[id].suggestedMin |
scales.[x/y]Axes.ticks.unitStepSize |
移除,使用 scales[id].ticks.stepSize |
scales.[x/y]Axes.ticks.userCallback |
改名为 scales[id].ticks.callback |
scales.[x/y]Axes.time.format |
改名为 scales[id].time.parser |
scales.[x/y]Axes.time.max |
改名为 scales[id].max |
scales.[x/y]Axes.time.min |
改名为 scales[id].min |
scales.[x/y]Axes.zeroLine* 系列选项 |
移除,改用 scriptable scale options |
数据集选项 steppedLine |
移除,使用 stepped |
图表选项 showLines |
改名为 showLine,与数据集选项一致(当前默认值见 core.defaults.js 的 showLine: true) |
图表选项 startAngle |
移到 radial 刻度选项 |
| 覆盖平台类 | 在 config 对象中传入 platform: PlatformClass。注意传的是类而不是实例;core.controller.js 中对应 `new (config.platform |
aspectRatio 默认值 |
doughnut、pie、polarArea、radar 图表默认变为 1 |
TimeScale 从对象数据读取 t |
不再默认读取 t,默认属性为 x 或 y(取决于方向),如何修改见 数据结构 |
tooltips 命名空间 |
改名为 tooltip,与插件名一致 |
legend、title、tooltip 命名空间 |
从 options 移到 options.plugins |
tooltips.custom |
改名为 plugins.tooltip.external |
默认值体系(Defaults)
defaults中的global命名空间被移除:Chart.defaults.global现在就是Chart.defaults。- 数据集控制器的默认值移到
overrides:例如Chart.defaults.line现在是Chart.overrides.line。 - 默认值去掉了
default前缀:例如Chart.defaults.global.defaultColor现在是Chart.defaults.color。 defaultColor被拆分为color、borderColor和backgroundColor(三者当前默认值见 core.defaults.js)。defaultFontColor改名为color。defaultFontFamily改名为font.family。defaultFontSize改名为font.size。defaultFontStyle改名为font.style。defaultLineHeight改名为font.lineHeight。- 横向柱状图的默认 tooltip 交互模式由
'index'改为'nearest',以匹配竖向柱状图。 legend、title、tooltip命名空间从Chart.defaults移到Chart.defaults.plugins。elements.line.fill默认值由true改为false。- Line 图表不再覆盖默认的
interaction模式:默认值由'index'改为'nearest'。当前 core.defaults.js 中interaction默认为{mode: 'nearest', intersect: true, includeInvisible: false},与此一致。
overrides 在源码中的形态是 core.defaults.js 的独立对象,Defaults.override(scope, values) 方法(L109-L111)负责写入它。
坐标轴(Scales):v3 中最大的变化
v3 中坐标轴配置是变化最大的部分:xAxes/yAxes 数组被移除,每一条轴现在是以 scale id 为键的独立 scale。
v2 配置:
options: {
scales: {
xAxes: [{
id: 'x',
type: 'time',
display: true,
title: {
display: true,
text: 'Date'
},
ticks: {
major: {
enabled: true
},
font: function(context) {
if (context.tick && context.tick.major) {
return {
weight: 'bold',
color: '#FF0000'
};
}
}
}
}],
yAxes: [{
id: 'y',
display: true,
title: {
display: true,
text: 'value'
}
}]
}
}
对应 v3 配置:
options: {
scales: {
x: {
type: 'time',
display: true,
title: {
display: true,
text: 'Date'
},
ticks: {
major: {
enabled: true
},
color: (context) => context.tick && context.tick.major && '#FF0000',
font: function(context) {
if (context.tick && context.tick.major) {
return {
weight: 'bold'
};
}
}
}
},
y: {
display: true,
title: {
display: true,
text: 'value'
}
}
}
}
注意:2.x 中“按 ticks 内的函数返回完整样式”的写法,在 v3 里拆成了多个可 scriptable 的属性(如 ticks.color、ticks.font),这与上面“proxy 解析 + scriptable”的通用机制一致。
源码层面,scales 以 id 为键的组织方式体现在 core.controller.js 的 ensureScalesHaveIDs(把 options.scales 的键直接写成 axisOptions.id)以及 buildOrUpdateScales(按 id 复用或新建 scale 实例,未使用的 id 会被清理)。
另外两条与 time 刻度相关的变更:
distribution: 'series'选项被移除,取而代之的是新的 scale 类型timeseries;- time 刻度的
autoSkip现在与其他刻度保持一致,默认开启。
动画(Animations)
动画系统在 v3 中被完全重写,现在每个属性都可以独立配置动画,详见 动画。
当前实现中,动画由两个协作部分组成:单例 Animator(基于 requestAnimFrame 的轮询循环,start/stop/running/add 管理各图表的动画项,并触发 progress/complete 监听器)以及 core.controller.js 中把 onComplete/onProgress 回调挂到 animator 上的逻辑。Chart.Animation.animationObject 改名为 Chart.Animation、chartInstance 改名为 chart 的 API 变化,正是服务于这套新结构。
可定制性(Customizability)
- 元素的
custom属性被移除,请改用 scriptable options。 - scriptable options 的
context对象中,hover属性改名为active,以对齐 datalabels 插件的命名。
交互(Interactions)
- 为支持 DRY 配置,新增了交互选项的根作用域:
options.hover与options.plugins.tooltip现在都从options.interaction派生。默认值定义在defaults.interaction层,因此 hover 与 tooltip 交互默认共享同一套 mode 等设置(当前默认值{mode: 'nearest', intersect: true, includeInvisible: false}见 core.defaults.js,且hover通过_fallback: 'interaction'描述符路由到interaction)。 - 交互命中范围被限制在图表区域 + 允许的溢出(overflow)之内。
{mode: 'label'}被{mode: 'index'}取代;{mode: 'single'}被{mode: 'nearest', intersect: true}取代;modes['X-axis']被{mode: 'index', intersect: false}取代;options.onClick现在只在图表区域内生效;options.onClick与options.onHover现在会收到chart实例作为第 3 个参数;options.onHover现在收到一个包装后的event作为第 1 个参数,原参数值可通过event.native访问。options.hover.onHover被移除,使用options.onHover。
交互模式的实现集中在 core.interaction.js:modes 对象只提供 index、dataset、point、nearest、x、y 五种模式——label/single/X-axis 在 v3 中确实不复存在,需要按上表改写。
刻度与网格(Ticks / Grid)
options.gridLines改名为options.grid;options.gridLines.offsetGridLines改名为options.grid.offset;options.gridLines.tickMarkLength改名为options.grid.tickLength;options.ticks.fixedStepSize不再使用,改用options.ticks.stepSize;options.ticks.major与options.ticks.minor被 tick 字体的 scriptable options 取代;Chart.Ticks.formatters.linear改名为Chart.Ticks.formatters.numeric;options.ticks.backdropPaddingX与options.ticks.backdropPaddingY在 radial linear 刻度中被options.ticks.backdropPadding取代。
Tooltip
xLabel与yLabel被移除,请改用label与formattedValue;filter选项调用时会收到额外参数,方法签名应为function(tooltipItem, index, tooltipItems, data);custom回调现在接收一个带tooltip和chart属性的 context 对象;- tooltip 模型中所有与 tooltip 选项相关的属性都移入
options属性内; - 回调不再接收
data参数,tooltip item 参数里直接携带 chart 和 dataset; - tooltip item 的
index改名为dataIndex,value改名为formattedValue; xPadding与yPadding合并为单个padding对象。
开发者迁移
终端用户的迁移相对直接,但面向插件作者、自定义控制器/刻度开发者的迁移更复杂。文档提示:如果需要迁移帮助,可以在项目社区渠道(#dev Discord)提问。以下按“移除 / 改名 / 行为变化”三类完整列出变更。
移除的 API
从 Chart 移除
Chart.animationServiceChart.activeChart.borderWidthChart.chart.chartChart.Bar:新图表通过new Chart并提供相应type参数创建Chart.Bubble:同上Chart.ChartChart.ControllerChart.Doughnut:同上Chart.innerRadius:现位于 doughnut、pie、polarArea 控制器上Chart.lastActiveChart.Legend:移到Chart.plugins.legend._element并变为私有Chart.Line:同Chart.BarChart.LinearScaleBase:需自行 import,不能从Chart对象访问Chart.offsetXChart.offsetYChart.outerRadius:现位于 doughnut、pie、polarArea 控制器上Chart.plugins:被Chart.registry取代(当前 core.controller.js 中static registry = registry)。插件默认值现在位于Chart.defaults.plugins[id]Chart.plugins.register:被Chart.register取代Chart.PolarArea:同Chart.BarChart.prototype.generateLegendChart.platform:原本只包含disableCSSInjection,v3 永不注入 CSS,故移除Chart.PluginBaseChart.Radar:同Chart.BarChart.radiusLengthChart.scaleService:被Chart.registry取代。刻度默认值现在位于Chart.defaults.scales[type]Chart.Scatter:同Chart.BarChart.typesChart.Title:移到Chart.plugins.title._element并变为私有Chart.Tooltip:现在由 tooltip 插件提供,positioners 可从tooltipPlugin.positioners访问ILayoutItem.minSize
从 Dataset Controller 移除
BarController.getDatasetMeta().barDatasetController.addElementAndResetDatasetController.createMetaDataDatasetController.createMetaDatasetDoughnutController.getRingIndex
从 Elements 移除
Element.getAreaElement.heightElement.hidden:被 chart 级状态取代,可用getDataVisibility(index)/toggleDataVisibility(index)(当前实现见 core.controller.js)Element.initializeElement.inLabelRangeLine.calculatePointY
从 Helpers 移除
helpers.addEventhelpers.aliasPixelhelpers.arrayEqualshelpers.configMergehelpers.findIndexhelpers.findNextWherehelpers.findPreviousWherehelpers.extend:改用Object.assignhelpers.getValueAtIndexOrDefault:改用helpers.resolvehelpers.indexOfhelpers.lineTohelpers.longestText:变为私有helpers.maxhelpers.measureText:变为私有helpers.minhelpers.nextItemhelpers.niceNumhelpers.numberOfLabelLineshelpers.previousItemhelpers.removeEventhelpers.roundedRecthelpers.scaleMergehelpers.where
从 Layout 移除
Layout.defaults
从 Scales 移除
LinearScaleBase.handleDirectionalChangesLogarithmicScale.minNotZeroScale.getRightValueScale.longestLabelWidthScale.longestTextCache:变为私有Scale.margins:变为私有Scale.mergeTicksOptionsScale.ticksAsNumbersScale.tickValues:变为私有TimeScale.getLabelCapacity:变为私有TimeScale.tickFormatFunction:变为私有
从 Plugins(Legend、Title、Tooltip)移除
IPlugin.afterScaleUpdate:改用afterLayoutLegend.margins:变为私有- Legend 的
onClick、onHover、onLeave选项现在除了隐式的this之外,还会把 legend 作为第 3 个参数传入 - Legend 的
onClick、onHover、onLeave选项现在第 1 个参数是包装后的event,原值可通过event.native访问 Title.margins:变为私有- tooltip item 的
x与y属性被element取代,可改用element.x、element.y或element.tooltipPosition()
移除的公共 API
以下公共 API 被移除并给出了替代写法:
getElementAtEvent→chart.getElementsAtEventForMode(e, 'nearest', { intersect: true }, false)getElementsAtEvent→chart.getElementsAtEventForMode(e, 'index', { intersect: true }, false)getElementsAtXAxis→chart.getElementsAtEventForMode(e, 'index', { intersect: false }, false)getDatasetAtEvent→chart.getElementsAtEventForMode(e, 'dataset', { intersect: true }, false)
getElementsAtEventForMode 的实现见 core.controller.js:它直接查 Interaction.modes[mode] 并调用对应方法,模式名与上面 modes 对象中的键一一对应。
移除的私有 API
Chart._bufferedRenderChart._updatingChart.data.datasets[datasetIndex]._metaDatasetController._getIndexScaleIdDatasetController._getIndexScaleDatasetController._getValueScaleIdDatasetController._getValueScaleElement._ctxElement._modelElement._viewLogarithmicScale._valueOffsetTimeScale.getPixelForOffsetTimeScale.getLabelWidthTooltip._lastActive
改名的 API
Chart.Animation.animationObject→Chart.AnimationChart.Animation.chartInstance→Chart.Animation.chartChart.canvasHelpers合并进Chart.helpersChart.elements.Arc→Chart.elements.ArcElementChart.elements.Line→Chart.elements.LineElementChart.elements.Point→Chart.elements.PointElementChart.elements.Rectangle→Chart.elements.BarElementChart.layoutService→Chart.layoutsChart.pluginService→Chart.pluginshelpers.callCallback→helpers.callbackhelpers.drawRoundedRectangle→helpers.roundedRecthelpers.getValueOrDefault→helpers.valueOrDefaultLayoutItem.fullWidth→LayoutItem.fullSizePoint.controlPointPreviousX→Point.cp1xPoint.controlPointPreviousY→Point.cp1yPoint.controlPointNextX→Point.cp2xPoint.controlPointNextY→Point.cp2yScale.calculateTickRotation→Scale.calculateLabelRotationTooltip.options.legendColorBackgroupd→Tooltip.options.multiKeyBackground
改名的私有 API:
BarController.calculateBarIndexPixels→BarController._calculateBarIndexPixelsBarController.calculateBarValuePixels→BarController._calculateBarValuePixelsBarController.getStackCount→BarController._getStackCountBarController.getStackIndex→BarController._getStackIndexBarController.getRuler→BarController._getRulerChart.destroyDatasetMeta→Chart._destroyDatasetMetaChart.drawDataset→Chart._drawDatasetChart.drawDatasets→Chart._drawDatasetsChart.eventHandler→Chart._eventHandlerChart.handleEvent→Chart._handleEventChart.initialize→Chart._initializeChart.resetElements→Chart._resetElementsChart.unbindEvents→Chart._unbindEventsChart.updateDataset→Chart._updateDatasetChart.updateDatasets→Chart._updateDatasetsChart.updateLayout→Chart._updateLayoutDatasetController.destroy→DatasetController._destroyDatasetController.insertElements→DatasetController._insertElementsDatasetController.onDataPop→DatasetController._onDataPopDatasetController.onDataPush→DatasetController._onDataPushDatasetController.onDataShift→DatasetController._onDataShiftDatasetController.onDataSplice→DatasetController._onDataSpliceDatasetController.onDataUnshift→DatasetController._onDataUnshiftDatasetController.removeElements→DatasetController._removeElementsDatasetController.resyncElements→DatasetController._resyncElementsLayoutItem.isFullWidth→LayoutItem.isFullSizeRadialLinearScale.setReductions→RadialLinearScale._setReductionsRadialLinearScale.pointLabels→RadialLinearScale._pointLabelsScale.handleMargins→Scale._handleMargins
签名与行为变化
动画系统重写带来的影响
动画系统被完全重写且性能更好:
Element._model与Element._view不再使用,属性直接设置在元素上。在inXRange/inYRange、getCenterPoint等大多数方法内部需要访问这些属性时,必须改用getProps方法。示例可参考仓库内置的元素实现(src/elements 目录)。- 在控制器中构建元素时,现在建议调用
updateElement来提供元素属性;同时新增了getSharedOptions、includeOptions等方法跳过冗余计算。示例可参考仓库内置的控制器(src/controllers 目录)。
getProps 的用法在交互代码中随处可见,例如 core.interaction.js 中 element.getProps(['startAngle', 'endAngle'], useFinalPosition)。
新的数据解析(Parsing)API
刻度引入了新的解析 API:把用户数据转换成更标准的格式。例如允许用户以 string 形式提供数值数据,并在必要时转换为 number。此前这发生在渲染过程中的“临时”阶段,现在提前到数据进入图表时统一完成,并且当用户提供的数据本身格式正确时可以跳过解析以获得更好性能。
- 如果你使用标准数据格式(
x/y),通常不需要做任何事; - 如果使用自定义数据格式(如金融图的
{o, h, l, c}),需要覆盖 core.datasetController.js 中的部分 parse 方法。迁移指南以使用 OHLC 数据格式的 chartjs-chart-financial 项目为范例(该示例位于 Chart.js 生态仓库,本仓库中对应的是控制器基类的 parse 钩子)。
Options 相关的控制器影响
以下变化对所有控制器都更“直接”:
global从 defaults 命名空间中移除(它多余且时常不一致);- 数据集默认值现在挂在图表类型选项之下(2.x 中为兼容旧行为未能做到这一点),修复它是新图表开发者遇到的最大障碍;
- 刻度默认选项需按终端用户迁移部分描述更新(例如用
x而非xAxes、y而非yAxes)。
updateElement → updateElements
updateElement 被改为 updateElements,签名变为接收要更新的元素数组、起始索引 start、数量 count 和 mode。这带来了性能收益:更容易复用所有元素间公共的计算,减少函数调用次数。基类钩子在 core.datasetController.js 中为空实现 updateElements(element, start, count, mode) {},而 controller.bar.js、controller.line.js、controller.doughnut.js、controller.radar.js 等内置控制器均遵循该签名。
Scales 的变化
Scale.getLabelForIndex被scale.getLabelForValue取代;Scale.getPixelForValue现在只需要一个参数。对TimeScale来说,该参数必须是自 epoch 起的毫秒数。作为性能优化,可接受一个可选的第 2 个参数——数据点索引。
Ticks 相关:
Scale.afterBuildTicks现在与其他回调一样没有参数;Scale.buildTicks现在要求返回 tick 对象;Scale.convertTicksToLabels改名为generateTickLabels,并要求在输入 ticks 上设置label属性;Scale.ticks现在包含对象而不是字符串;- 开启
autoSkip时,Scale.ticks只包含未被跳过的 ticks,而不是全部 ticks; - ticks 现在总是按单调递增顺序生成。
Time Scale:
getValueForPixel现在返回自 epoch 起的毫秒数。
Controllers 的变化
Core Controller:
updateHoverStyle的第 1 个参数现在是一个包含element、datasetIndex、index的对象数组;resize的签名变化:移除了第 1 个silent参数(当前 core.controller.js 中resize(width, height)与私有_resize(width, height)的分离与该签名一致)。
Dataset Controllers:
updateElement被updateElements取代,接收待更新元素、start索引、count与mode;setHoverStyle与removeHoverStyle现在额外接收datasetIndex与index。
Interactions 的变化
交互模式的回调方法现在返回对象数组,每个对象包含 element、datasetIndex 与 index。这一点在 core.interaction.js 的 typedef 中定义:InteractionItem = {datasetIndex: number, index: number, element: Element},所有 modes 方法的返回值都遵循该结构。
Layout 的变化
ILayoutItem.update不再有返回值。
Helpers 的变化
所有 helpers 现在暴露在一个扁平层级中。例如 Chart.helpers.canvas.clipArea → Chart.helpers.clipArea。
Canvas helper 细节:
drawPoint的第 2 个参数现在是完整的 options 对象,不再显式传style、rotation、radius;helpers.getMaximumHeight被helpers.dom.getMaximumSize取代;helpers.getMaximumWidth被helpers.dom.getMaximumSize取代;helpers.clear改名为helpers.clearCanvas,现在接收canvas与可选的ctx参数(core.controller.js 中clearCanvas(canvas, ctx)的调用可见);helpers.retinaScale接受可选的第 3 个参数forceStyle,强制覆盖当前 canvas 样式;forceRatio不再回退到window.devicePixelRatio,而是默认为1。
Platform 的变化
Chart.platform不再是图表使用的平台对象,每个图表实例现在拥有独立的平台实例(core.controller.js 中this.platform = new (config.platform || _detectPlatform(initialCanvas))());Chart.platforms是一个对象,包含两个可用平台类BasicPlatform与DomPlatform,还包含所有平台必须继承的基类BasePlatform;- 如果传入的 canvas 是
OffscreenCanvas实例,会自动使用BasicPlatform; - platform 上新增
isAttached方法。
平台实现的三个基类分别位于 platform.base.js、platform.basic.js 与 platform.dom.js,与上述描述一致。
IPlugin 接口的变化
- 所有插件钩子统一为 3 个参数:
chart、args、options。以下钩子的签名因此变化:beforeInit、afterInit、reset、beforeLayout、afterLayout、beforeRender、afterRender、beforeDraw、afterDraw、beforeDatasetsDraw、afterDatasetsDraw、beforeEvent、afterEvent、resize、destroy; afterDatasetsUpdate、afterUpdate、beforeDatasetsUpdate、beforeUpdate现在接收args对象作为第 2 个参数;options参数始终在最后,从第 2 位移到第 3 位;afterEvent与beforeEvent现在把包装后的event作为第 2 个参数的event属性传入,原生事件可通过args.event.native访问;- 初始的
resize不再 silent,意味着resize事件可能发生在beforeInit与afterInit之间; - 新增钩子:
install、start、stop、uninstall; afterEvent应通过把args.changed设为true来声明需要渲染的变化。由于args在所有插件间共享,只应将其设为true而不应设为false。
在当前仓库(4.x)中复核这些变更
本文引用的仓库版本为 package.json 声明的 4.5.1,即 v3 迁移完成之后的后续版本。上文列出的 v3 破坏性变更在 4.x 源码中均保持为既有事实,迁移时可以放心地以当前源码为最终参照:
| 迁移要点 | 当前源码证据 |
|---|---|
options.scales 以 id 为键、x/y 直接配置 |
core.controller.js ensureScalesHaveIDs |
| 画布被占用时构造函数抛错 | core.controller.js |
Chart.register / Chart.registry 取代 Chart.plugins |
core.controller.js |
defaults 无 global 层、overrides 独立存在、interaction 默认 nearest |
core.defaults.js 与 L66-L70 |
交互模式仅剩 index/dataset/point/nearest/x/y,返回 {element, datasetIndex, index} |
core.interaction.js 与 L257-L386 |
| 重写后的动画系统(单例 Animator + 属性级动画) | core.animator.js |
控制器统一的 updateElements(data, start, count, mode) 签名 |
core.datasetController.js 及各内置控制器 |
getDataVisibility / toggleDataVisibility 取代 Element.hidden |
core.controller.js |
indexAxis 作为横向柱状图的替代方案 |
controller.bar.js |
moment 不再为依赖 |
package.json |
适用前提与小结
- 本文所有结论以 v3-migration.md 为准,适用于“从 Chart.js 2.x 升级到 3.0(以及基于 3.0 API 的 4.x)”的迁移场景;若你已经在 3.x/4.x 上开发,则只需把本文当作 2.x 旧配置的“翻译字典”。
- 迁移顺序建议:先改安装方式与注册(tree shaking),再按“具体选项改名表”批量替换配置键,然后处理
scales数组到对象的结构变化,最后检查交互模式、tooltip 回调签名与插件钩子签名这三处最容易在运行时暴露问题的 API。 - 对自定义数据格式的图表(非
x/y),重点核对 core.datasetController.js 中需要覆盖的 parse 方法,这是新 parsing API 唯一可能要求你改动代码的地方。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0623
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00