docs/migration/v3-migration.md
Chart.js 3.0 introduces a number of breaking changes. Chart.js 2.0 was released in April 2016. In the years since then, as Chart.js has grown in popularity and feature set, we've learned some lessons about how to better create a charting library. In order to improve performance, offer new features, and improve maintainability, it was necessary to break backwards compatibility, but we aimed to do so only when worth the benefit. Some major highlights of v3 include:
dist/chart.js.Chart.bundle.js and Chart.bundle.min.js. Please see the installation and integration docs for details on the recommended way to setup Chart.js if you were using these builds.moment is no longer specified as an npm dependency. If you are using the time or timeseries scales, you must include one of the available adapters and corresponding date library. You no longer need to exclude moment from your build.Chart constructor will throw an error if the canvas/context provided is already in usenpm module in a project and want to make use of this feature, you need to import and register the controllers, elements, scales and plugins you want to use, for a list of all the available items to import see integration. You will not have to call register if importing Chart.js via a script tag or from the auto register path as an npm module, in this case you will not get the tree shaking benefits. Here is an example of registering components: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'
}
}
}
})
horizontalBar chart type was removed. Horizontal bar charts can be configured using the new indexAxis optionA number of changes were made to the configuration options passed to the Chart constructor. Those changes are documented below.
backgroundColor: ['red', 'green'] will result in alternating 'red' / 'green' if there are more than 2 data points.elements.rectangle is now elements.barhover.animationDuration is now configured in animation.active.durationresponsiveAnimationDuration is now configured in animation.resize.durationelements.arc.angle is now configured in degrees instead of radians.startAngle option is now consistent with Radar, 0 is at top and value is in degrees. Default is changed from -½π to 0.rotation option is now in degrees and 0 is at top. Default is changed from -½π to 0.circumference option is now in degrees. Default is changed from 2π to 360.cutoutPercentage was renamed to cutoutand accepts pixels as number and percent as string ending with %.scale option was removed in favor of options.scales.r (or any other scale id, with axis: 'r')scales.[x/y]Axes arrays were removed. Scales are now configured directly to options.scales object with the object key being the scale Id.scales.[x/y]Axes.barPercentage was moved to dataset option barPercentagescales.[x/y]Axes.barThickness was moved to dataset option barThicknessscales.[x/y]Axes.categoryPercentage was moved to dataset option categoryPercentagescales.[x/y]Axes.maxBarThickness was moved to dataset option maxBarThicknessscales.[x/y]Axes.minBarLength was moved to dataset option minBarLengthscales.[x/y]Axes.scaleLabel was renamed to scales[id].titlescales.[x/y]Axes.scaleLabel.labelString was renamed to scales[id].title.textscales.[x/y]Axes.ticks.beginAtZero was renamed to scales[id].beginAtZeroscales.[x/y]Axes.ticks.max was renamed to scales[id].maxscales.[x/y]Axes.ticks.min was renamed to scales[id].minscales.[x/y]Axes.ticks.reverse was renamed to scales[id].reversescales.[x/y]Axes.ticks.suggestedMax was renamed to scales[id].suggestedMaxscales.[x/y]Axes.ticks.suggestedMin was renamed to scales[id].suggestedMinscales.[x/y]Axes.ticks.unitStepSize was removed. Use scales[id].ticks.stepSizescales.[x/y]Axes.ticks.userCallback was renamed to scales[id].ticks.callbackscales.[x/y]Axes.time.format was renamed to scales[id].time.parserscales.[x/y]Axes.time.max was renamed to scales[id].maxscales.[x/y]Axes.time.min was renamed to scales[id].minscales.[x/y]Axes.zeroLine* options of axes were removed. Use scriptable scale options instead.steppedLine was removed. Use steppedshowLines was renamed to showLine to match the dataset option.startAngle was moved to radial scale options.platform: PlatformClass in the config object. Note that the class should be passed, not an instance of the class.aspectRatio defaults to 1 for doughnut, pie, polarArea, and radar chartsTimeScale does not read t from object data by default anymore. The default property is x or y, depending on the orientation. See data structures for details on how to change the default.tooltips namespace was renamed to tooltip to match the plugin namelegend, title and tooltip namespaces were moved from options to options.plugins.tooltips.custom was renamed to plugins.tooltip.externalglobal namespace was removed from defaults. So Chart.defaults.global is now Chart.defaultsoverrides. For example Chart.defaults.line is now Chart.overrides.linedefault prefix was removed from defaults. For example Chart.defaults.global.defaultColor is now Chart.defaults.colordefaultColor was split to color, borderColor and backgroundColordefaultFontColor was renamed to colordefaultFontFamily was renamed to font.familydefaultFontSize was renamed to font.sizedefaultFontStyle was renamed to font.styledefaultLineHeight was renamed to font.lineHeight'index' to 'nearest' to match vertical bar chartslegend, title and tooltip namespaces were moved from Chart.defaults to Chart.defaults.plugins.elements.line.fill default changed from true to false.interaction mode. Default is changed from 'index' to 'nearest'.The configuration options for scales is the largest change in v3. The xAxes and yAxes arrays were removed and axis options are individual scales now keyed by scale ID.
The v2 configuration below is shown with it's new v3 configuration
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'
}
}]
}
}
And now, in 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'
}
}
}
}
distribution: 'series' was removed and a new scale type timeseries was introduced in its placeautoSkip is now enabled by default for consistency with the other scalesAnimation system was completely rewritten in Chart.js v3. Each property can now be animated separately. Please see animations docs for details.
custom attribute of elements was removed. Please use scriptable optionshover property of scriptable options context object was renamed to active to align it with the datalabels plugin.options.hover and options.plugins.tooltip now both extend from options.interaction. Defaults are defined at defaults.interaction level, so by default hover and tooltip interactions share the same mode etc.interactions are now limited to the chart area + allowed overflow{mode: 'label'} was replaced with {mode: 'index'}{mode: 'single'} was replaced with {mode: 'nearest', intersect: true}modes['X-axis'] was replaced with {mode: 'index', intersect: false}options.onClick is now limited to the chart areaoptions.onClick and options.onHover now receive the chart instance as a 3rd argumentoptions.onHover now receives a wrapped event as the first parameter. The previous first parameter value is accessible via event.native.options.hover.onHover was removed, use options.onHover.options.gridLines was renamed to options.gridoptions.gridLines.offsetGridLines was renamed to options.grid.offset.options.gridLines.tickMarkLength was renamed to options.grid.tickLength.options.ticks.fixedStepSize is no longer used. Use options.ticks.stepSize.options.ticks.major and options.ticks.minor were replaced with scriptable options for tick fonts.Chart.Ticks.formatters.linear was renamed to Chart.Ticks.formatters.numeric.options.ticks.backdropPaddingX and options.ticks.backdropPaddingY were replaced with options.ticks.backdropPadding in the radial linear scale.xLabel and yLabel were removed. Please use label and formattedValuefilter option will now be passed additional parameters when called and should have the method signature function(tooltipItem, index, tooltipItems, data)custom callback now takes a context object that has tooltip and chart propertiesoptions property.data parameter. The tooltip item parameter contains the chart and dataset insteadindex parameter was renamed to dataIndex and value was renamed to formattedValuexPadding and yPadding options were merged into a single padding objectWhile the end-user migration for Chart.js 3 is fairly straight-forward, the developer migration can be more complicated. Please reach out for help in the #dev Discord channel if tips on migrating would be helpful.
Some of the biggest things that have changed:
Element._model and Element._view are no longer used and properties are now set directly on the elements. You will have to use the method getProps to access these properties inside most methods such as inXRange/inYRange and getCenterPoint. Please take a look at the Chart.js-provided elements for examples.updateElement to provide the element properties. There are also methods such as getSharedOptions and includeOptions that have been added to skip redundant computation. Please take a look at the Chart.js-provided controllers for examples.string and converts it to a number where necessary. Previously this was done on the fly as charts were rendered. Now it's done up front with the ability to skip it for better performance if users provide data in the correct format. If you're using standard data format like x/y you may not need to do anything. If you're using a custom data format you will have to override some of the parse methods in core.datasetController.js. An example can be found in chartjs-chart-financial, which uses an {o, h, l, c} data format.A few changes were made to controllers that are more straight-forward, but will affect all controllers:
global was removed from the defaults namespace as it was unnecessary and sometimes inconsistentx instead of xAxes and y instead of yAxes)updateElement was changed to updateElements and has a new method signature as described below. This provides performance enhancements such as allowing easier reuse of computations that are common to all elements and reducing the number of function callsThe following properties and methods were removed:
Chart.animationServiceChart.activeChart.borderWidthChart.chart.chartChart.Bar. New charts are created via new Chart and providing the appropriate type parameterChart.Bubble. New charts are created via new Chart and providing the appropriate type parameterChart.ChartChart.ControllerChart.Doughnut. New charts are created via new Chart and providing the appropriate type parameterChart.innerRadius now lives on doughnut, pie, and polarArea controllersChart.lastActiveChart.Legend was moved to Chart.plugins.legend._element and made privateChart.Line. New charts are created via new Chart and providing the appropriate type parameterChart.LinearScaleBase now must be imported and cannot be accessed off the Chart objectChart.offsetXChart.offsetYChart.outerRadius now lives on doughnut, pie, and polarArea controllersChart.plugins was replaced with Chart.registry. Plugin defaults are now in Chart.defaults.plugins[id].Chart.plugins.register was replaced by Chart.register.Chart.PolarArea. New charts are created via new Chart and providing the appropriate type parameterChart.prototype.generateLegendChart.platform. It only contained disableCSSInjection. CSS is never injected in v3.Chart.PluginBaseChart.Radar. New charts are created via new Chart and providing the appropriate type parameterChart.radiusLengthChart.scaleService was replaced with Chart.registry. Scale defaults are now in Chart.defaults.scales[type].Chart.Scatter. New charts are created via new Chart and providing the appropriate type parameterChart.typesChart.Title was moved to Chart.plugins.title._element and made privateChart.Tooltip is now provided by the tooltip plugin. The positioners can be accessed from tooltipPlugin.positionersILayoutItem.minSizeBarController.getDatasetMeta().barDatasetController.addElementAndResetDatasetController.createMetaDataDatasetController.createMetaDatasetDoughnutController.getRingIndexElement.getAreaElement.heightElement.hidden was replaced by chart level status, usable with getDataVisibility(index) / toggleDataVisibility(index)Element.initializeElement.inLabelRangeLine.calculatePointYhelpers.addEventhelpers.aliasPixelhelpers.arrayEqualshelpers.configMergehelpers.findIndexhelpers.findNextWherehelpers.findPreviousWherehelpers.extend. Use Object.assign insteadhelpers.getValueAtIndexOrDefault. Use helpers.resolve instead.helpers.indexOfhelpers.lineTohelpers.longestText was made privatehelpers.maxhelpers.measureText was made privatehelpers.minhelpers.nextItemhelpers.niceNumhelpers.numberOfLabelLineshelpers.previousItemhelpers.removeEventhelpers.roundedRecthelpers.scaleMergehelpers.whereLayout.defaultsLinearScaleBase.handleDirectionalChangesLogarithmicScale.minNotZeroScale.getRightValueScale.longestLabelWidthScale.longestTextCache is now privateScale.margins is now privateScale.mergeTicksOptionsScale.ticksAsNumbersScale.tickValues is now privateTimeScale.getLabelCapacity is now privateTimeScale.tickFormatFunction is now privateIPlugin.afterScaleUpdate. Use afterLayout insteadLegend.margins is now privateonClick, onHover, and onLeave options now receive the legend as the 3rd argument in addition to implicitly via thisonClick, onHover, and onLeave options now receive a wrapped event as the first parameter. The previous first parameter value is accessible via event.native.Title.margins is now privatex and y attributes were replaced by element. You can use element.x and element.y or element.tooltipPosition() instead.The following public APIs were removed.
getElementAtEvent is replaced with chart.getElementsAtEventForMode(e, 'nearest', { intersect: true }, false)getElementsAtEvent is replaced with chart.getElementsAtEventForMode(e, 'index', { intersect: true }, false)getElementsAtXAxis is replaced with chart.getElementsAtEventForMode(e, 'index', { intersect: false }, false)getDatasetAtEvent is replaced with chart.getElementsAtEventForMode(e, 'dataset', { intersect: true }, false)The following private APIs were removed.
Chart._bufferedRenderChart._updatingChart.data.datasets[datasetIndex]._metaDatasetController._getIndexScaleIdDatasetController._getIndexScaleDatasetController._getValueScaleIdDatasetController._getValueScaleElement._ctxElement._modelElement._viewLogarithmicScale._valueOffsetTimeScale.getPixelForOffsetTimeScale.getLabelWidthTooltip._lastActiveThe following properties were renamed during v3 development:
Chart.Animation.animationObject was renamed to Chart.AnimationChart.Animation.chartInstance was renamed to Chart.Animation.chartChart.canvasHelpers was merged with Chart.helpersChart.elements.Arc was renamed to Chart.elements.ArcElementChart.elements.Line was renamed to Chart.elements.LineElementChart.elements.Point was renamed to Chart.elements.PointElementChart.elements.Rectangle was renamed to Chart.elements.BarElementChart.layoutService was renamed to Chart.layoutsChart.pluginService was renamed to Chart.pluginshelpers.callCallback was renamed to helpers.callbackhelpers.drawRoundedRectangle was renamed to helpers.roundedRecthelpers.getValueOrDefault was renamed to helpers.valueOrDefaultLayoutItem.fullWidth was renamed to LayoutItem.fullSizePoint.controlPointPreviousX was renamed to Point.cp1xPoint.controlPointPreviousY was renamed to Point.cp1yPoint.controlPointNextX was renamed to Point.cp2xPoint.controlPointNextY was renamed to Point.cp2yScale.calculateTickRotation was renamed to Scale.calculateLabelRotationTooltip.options.legendColorBackgroupd was renamed to Tooltip.options.multiKeyBackgroundThe private APIs listed below were renamed:
BarController.calculateBarIndexPixels was renamed to BarController._calculateBarIndexPixelsBarController.calculateBarValuePixels was renamed to BarController._calculateBarValuePixelsBarController.getStackCount was renamed to BarController._getStackCountBarController.getStackIndex was renamed to BarController._getStackIndexBarController.getRuler was renamed to BarController._getRulerChart.destroyDatasetMeta was renamed to Chart._destroyDatasetMetaChart.drawDataset was renamed to Chart._drawDatasetChart.drawDatasets was renamed to Chart._drawDatasetsChart.eventHandler was renamed to Chart._eventHandlerChart.handleEvent was renamed to Chart._handleEventChart.initialize was renamed to Chart._initializeChart.resetElements was renamed to Chart._resetElementsChart.unbindEvents was renamed to Chart._unbindEventsChart.updateDataset was renamed to Chart._updateDatasetChart.updateDatasets was renamed to Chart._updateDatasetsChart.updateLayout was renamed to Chart._updateLayoutDatasetController.destroy was renamed to DatasetController._destroyDatasetController.insertElements was renamed to DatasetController._insertElementsDatasetController.onDataPop was renamed to DatasetController._onDataPopDatasetController.onDataPush was renamed to DatasetController._onDataPushDatasetController.onDataShift was renamed to DatasetController._onDataShiftDatasetController.onDataSplice was renamed to DatasetController._onDataSpliceDatasetController.onDataUnshift was renamed to DatasetController._onDataUnshiftDatasetController.removeElements was renamed to DatasetController._removeElementsDatasetController.resyncElements was renamed to DatasetController._resyncElementsLayoutItem.isFullWidth was renamed to LayoutItem.isFullSizeRadialLinearScale.setReductions was renamed to RadialLinearScale._setReductionsRadialLinearScale.pointLabels was renamed to RadialLinearScale._pointLabelsScale.handleMargins was renamed to Scale._handleMarginsThe APIs listed in this section have changed in signature or behaviour from version 2.
Scale.getLabelForIndex was replaced by scale.getLabelForValueScale.getPixelForValue now only requires one parameter. For the TimeScale that parameter must be millis since the epoch. As a performance optimization, it may take an optional second parameter, giving the index of the data point.Scale.afterBuildTicks now has no parameters like the other callbacksScale.buildTicks is now expected to return tick objectsScale.convertTicksToLabels was renamed to generateTickLabels. It is now expected to set the label property on the ticks given as inputScale.ticks now contains objects instead of stringsautoSkip option is enabled, Scale.ticks now contains only the non-skipped ticks instead of all ticks.getValueForPixel now returns milliseconds since the epochupdateHoverStyle is now an array of objects containing the element, datasetIndex, and indexresize changed, the first silent parameter was removed.updateElement was replaced with updateElements now taking the elements to update, the start index, count, and modesetHoverStyle and removeHoverStyle now additionally take the datasetIndex and indexelement, datasetIndex, and indexILayoutItem.update no longer has a return valueAll helpers are now exposed in a flat hierarchy, e.g., Chart.helpers.canvas.clipArea -> Chart.helpers.clipArea
drawPoint is now the full options object, so style, rotation, and radius are no longer passed explicitlyhelpers.getMaximumHeight was replaced by helpers.dom.getMaximumSizehelpers.getMaximumWidth was replaced by helpers.dom.getMaximumSizehelpers.clear was renamed to helpers.clearCanvas and now takes canvas and optionally ctx as parameter(s).helpers.retinaScale accepts optional third parameter forceStyle, which forces overriding current canvas style. forceRatio no longer falls back to window.devicePixelRatio, instead it defaults to 1.Chart.platform is no longer the platform object used by charts. Every chart instance now has a separate platform instance.Chart.platforms is an object that contains two usable platform classes, BasicPlatform and DomPlatform. It also contains BasePlatform, a class that all platforms must extend from.OffscreenCanvas, the BasicPlatform is automatically used.isAttached method was added to platform.chart, args and options. This means change in signature for these hooks: beforeInit, afterInit, reset, beforeLayout, afterLayout, beforeRender, afterRender, beforeDraw, afterDraw, beforeDatasetsDraw, afterDatasetsDraw, beforeEvent, afterEvent, resize, destroy.afterDatasetsUpdate, afterUpdate, beforeDatasetsUpdate, and beforeUpdate now receive args object as second argument. options argument is always the last and thus was moved from 2nd to 3rd place.afterEvent and beforeEvent now receive a wrapped event as the event property of the second argument. The native event is available via args.event.native.resize is no longer silent. Meaning that resize event can fire between beforeInit and afterInitinstall, start, stop, and uninstallafterEvent should notify about changes that need a render by setting args.changed to true. Because the args are shared with all plugins, it should only be set to true and not false.