# 3.x Migration Guide
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:
- Large performance improvements including the ability to skip data parsing and render charts in parallel via webworkers
- Additional configurability and scriptable options with better defaults
- Completely rewritten animation system
- Rewritten filler plugin with numerous bug fixes
- Documentation migrated from GitBook to Vuepress
- API documentation generated and verified by TypeDoc
- No more CSS injection
- Tons of bug fixes
- Tree shaking
# End user migration
# Setup and installation
- Distributed files are now in lower case. For example:
dist/chart.js. - Chart.js is no longer providing the
Chart.bundle.jsandChart.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. momentis no longer specified as an npm dependency. If you are using thetimeortimeseriesscales, you must include one of the available adapters (opens new window) and corresponding date library. You no longer need to exclude moment from your build.- The
Chartconstructor will throw an error if the canvas/context provided is already in use - Chart.js 3 is tree-shakeable. So if you are using it as an
npmmodule 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 callregisterif importing Chart.js via ascripttag or from theautoregister path as annpmmodule, 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'
}
}
}
})
# Chart types
horizontalBarchart type was removed. Horizontal bar charts can be configured using the newindexAxisoption
# Options
A number of changes were made to the configuration options passed to the Chart constructor. Those changes are documented below.
# Generic changes
- Indexable options are now looping.
backgroundColor: ['red', 'green']will result in alternating'red'/'green'if there are more than 2 data points. - The input properties of object data can now be freely specified, see data structures for details.
- Most options are resolved utilizing proxies, instead of merging with defaults. In addition to easily enabling different resolution routes for different contexts, it allows using other resolved options in scriptable options.
- Options are by default scriptable and indexable, unless disabled for some reason.
- Scriptable options receive a option resolver as second parameter for accessing other options in same context.
- Resolution falls to upper scopes, if no match is found earlier. See options for details.
# Specific changes
elements.rectangleis nowelements.barhover.animationDurationis now configured inanimation.active.durationresponsiveAnimationDurationis now configured inanimation.resize.duration- Polar area
elements.arc.angleis now configured in degrees instead of radians. - Polar area
startAngleoption is now consistent withRadar, 0 is at top and value is in degrees. Default is changed from-½πto0. - Doughnut
rotationoption is now in degrees and 0 is at top. Default is changed from-½πto0. - Doughnut
circumferenceoption is now in degrees. Default is changed from2πto360. - Doughnut
cutoutPercentagewas renamed tocutoutand accepts pixels as number and percent as string ending with%. scaleoption was removed in favor ofoptions.scales.r(or any other scale id, withaxis: 'r')scales.[x/y]Axesarrays were removed. Scales are now configured directly tooptions.scalesobject with the object key being the scale Id.scales.[x/y]Axes.barPercentagewas moved to dataset optionbarPercentagescales.[x/y]Axes.barThicknesswas moved to dataset optionbarThicknessscales.[x/y]Axes.categoryPercentagewas moved to dataset optioncategoryPercentagescales.[x/y]Axes.maxBarThicknesswas moved to dataset optionmaxBarThicknessscales.[x/y]Axes.minBarLengthwas moved to dataset optionminBarLengthscales.[x/y]Axes.scaleLabelwas renamed toscales[id].titlescales.[x/y]Axes.scaleLabel.labelStringwas renamed toscales[id].title.textscales.[x/y]Axes.ticks.beginAtZerowas renamed toscales[id].beginAtZeroscales.[x/y]Axes.ticks.maxwas renamed toscales[id].maxscales.[x/y]Axes.ticks.minwas renamed toscales[id].minscales.[x/y]Axes.ticks.reversewas renamed toscales[id].reversescales.[x/y]Axes.ticks.suggestedMaxwas renamed toscales[id].suggestedMaxscales.[x/y]Axes.ticks.suggestedMinwas renamed toscales[id].suggestedMinscales.[x/y]Axes.ticks.unitStepSizewas removed. Usescales[id].ticks.stepSizescales.[x/y]Axes.ticks.userCallbackwas renamed toscales[id].ticks.callbackscales.[x/y]Axes.time.formatwas renamed toscales[id].time.parserscales.[x/y]Axes.time.maxwas renamed toscales[id].maxscales.[x/y]Axes.time.minwas renamed toscales[id].minscales.[x/y]Axes.zeroLine*options of axes were removed. Use scriptable scale options instead.- The dataset option
steppedLinewas removed. Usestepped - The chart option
showLineswas renamed toshowLineto match the dataset option. - The chart option
startAnglewas moved toradialscale options. - To override the platform class used in a chart instance, pass
platform: PlatformClassin the config object. Note that the class should be passed, not an instance of the class. aspectRatiodefaults to 1 for doughnut, pie, polarArea, and radar chartsTimeScaledoes not readtfrom object data by default anymore. The default property isxory, depending on the orientation. See data structures for details on how to change the default.tooltipsnamespace was renamed totooltipto match the plugin namelegend,titleandtooltipnamespaces were moved fromoptionstooptions.plugins.tooltips.customwas renamed toplugins.tooltip.external
# Defaults
globalnamespace was removed fromdefaults. SoChart.defaults.globalis nowChart.defaults- Dataset controller defaults were relocate to
overrides. For exampleChart.defaults.lineis nowChart.overrides.line defaultprefix was removed from defaults. For exampleChart.defaults.global.defaultColoris nowChart.defaults.colordefaultColorwas split tocolor,borderColorandbackgroundColordefaultFontColorwas renamed tocolordefaultFontFamilywas renamed tofont.familydefaultFontSizewas renamed tofont.sizedefaultFontStylewas renamed tofont.styledefaultLineHeightwas renamed tofont.lineHeight- Horizontal Bar default tooltip mode was changed from
'index'to'nearest'to match vertical bar charts legend,titleandtooltipnamespaces were moved fromChart.defaultstoChart.defaults.plugins.elements.line.filldefault changed fromtruetofalse.- Line charts no longer override the default
interactionmode. Default is changed from'index'to'nearest'.
# Scales
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'
}
}
}
}
- The time scale option
distribution: 'series'was removed and a new scale typetimeserieswas introduced in its place - In the time scale,
autoSkipis now enabled by default for consistency with the other scales
# Animations
Animation system was completely rewritten in Chart.js v3. Each property can now be animated separately. Please see animations docs for details.
# Customizability
customattribute of elements was removed. Please use scriptable options- The
hoverproperty of scriptable optionscontextobject was renamed toactiveto align it with the datalabels plugin.
# Interactions
- To allow DRY configuration, a root options scope for common interaction options was added.
options.hoverandoptions.plugins.tooltipnow both extend fromoptions.interaction. Defaults are defined atdefaults.interactionlevel, so by default hover and tooltip interactions share the same mode etc. interactionsare 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.onClickis now limited to the chart areaoptions.onClickandoptions.onHovernow receive thechartinstance as a 3rd argumentoptions.onHovernow receives a wrappedeventas the first parameter. The previous first parameter value is accessible viaevent.native.options.hover.onHoverwas removed, useoptions.onHover.
# Ticks
options.gridLineswas renamed tooptions.gridoptions.gridLines.offsetGridLineswas renamed tooptions.grid.offset.options.gridLines.tickMarkLengthwas renamed tooptions.grid.tickLength.options.ticks.fixedStepSizeis no longer used. Useoptions.ticks.stepSize.options.ticks.majorandoptions.ticks.minorwere replaced with scriptable options for tick fonts.Chart.Ticks.formatters.linearwas renamed toChart.Ticks.formatters.numeric.options.ticks.backdropPaddingXandoptions.ticks.backdropPaddingYwere replaced withoptions.ticks.backdropPaddingin the radial linear scale.
# Tooltip
xLabelandyLabelwere removed. Please uselabelandformattedValue- The
filteroption will now be passed additional parameters when called and should have the method signaturefunction(tooltipItem, index, tooltipItems, data) - The
customcallback now takes a context object that hastooltipandchartproperties - All properties of tooltip model related to the tooltip options have been moved to reside within the
optionsproperty. - The callbacks no longer are given a
dataparameter. The tooltip item parameter contains the chart and dataset instead - The tooltip item's
indexparameter was renamed todataIndexandvaluewas renamed toformattedValue - The
xPaddingandyPaddingoptions were merged into a singlepaddingobject
# Developer migration
While 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 Slack (opens new window) channel if tips on migrating would be helpful.
Some of the biggest things that have changed:
- There is a completely rewritten and more performant animation system.
Element._modelandElement._vieware no longer used and properties are now set directly on the elements. You will have to use the methodgetPropsto access these properties inside most methods such asinXRange/inYRangeandgetCenterPoint. Please take a look at the Chart.js-provided elements (opens new window) for examples.- When building the elements in a controller, it's now suggested to call
updateElementto provide the element properties. There are also methods such asgetSharedOptionsandincludeOptionsthat have been added to skip redundant computation. Please take a look at the Chart.js-provided controllers (opens new window) for examples.
- Scales introduced a new parsing API. This API takes user data and converts it into a more standard format. E.g. it allows users to provide numeric data as a
stringand converts it to anumberwhere 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 likex/yyou may not need to do anything. If you're using a custom data format you will have to override some of the parse methods incore.datasetController.js. An example can be found in chartjs-chart-financial (opens new window), 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:
- Options:
globalwas removed from the defaults namespace as it was unnecessary and sometimes inconsistent- Dataset defaults are now under the chart type options instead of vice-versa. This was not able to be done when introduced in 2.x for backwards compatibility. Fixing it removes the biggest stumbling block that new chart developers encountered
- Scale default options need to be updated as described in the end user migration section (e.g.
xinstead ofxAxesandyinstead ofyAxes)
updateElementwas changed toupdateElementsand 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 calls
# Removed
The following properties and methods were removed:
# Removed from Chart
Chart.animationServiceChart.activeChart.borderWidthChart.chart.chartChart.Bar. New charts are created vianew Chartand providing the appropriatetypeparameterChart.Bubble. New charts are created vianew Chartand providing the appropriatetypeparameterChart.ChartChart.ControllerChart.Doughnut. New charts are created vianew Chartand providing the appropriatetypeparameterChart.innerRadiusnow lives on doughnut, pie, and polarArea controllersChart.lastActiveChart.Legendwas moved toChart.plugins.legend._elementand made privateChart.Line. New charts are created vianew Chartand providing the appropriatetypeparameterChart.LinearScaleBasenow must be imported and cannot be accessed off theChartobjectChart.offsetXChart.offsetYChart.outerRadiusnow lives on doughnut, pie, and polarArea controllersChart.pluginswas replaced withChart.registry. Plugin defaults are now inChart.defaults.plugins[id].Chart.plugins.registerwas replaced byChart.register.Chart.PolarArea. New charts are created vianew Chartand providing the appropriatetypeparameterChart.prototype.generateLegendChart.platform. It only containeddisableCSSInjection. CSS is never injected in v3.Chart.PluginBaseChart.Radar. New charts are created vianew Chartand providing the appropriatetypeparameterChart.radiusLengthChart.scaleServicewas replaced withChart.registry. Scale defaults are now inChart.defaults.scales[type].Chart.Scatter. New charts are created vianew Chartand providing the appropriatetypeparameterChart.typesChart.Titlewas moved toChart.plugins.title._elementand made privateChart.Tooltipis now provided by the tooltip plugin. The positioners can be accessed fromtooltipPlugin.positionersILayoutItem.minSize
# Removed from Dataset Controllers
BarController.getDatasetMeta().barDatasetController.addElementAndResetDatasetController.createMetaDataDatasetController.createMetaDatasetDoughnutController.getRingIndex
# Removed from Elements
Element.getAreaElement.heightElement.hiddenwas replaced by chart level status, usable withgetDataVisibility(index)/toggleDataVisibility(index)Element.initializeElement.inLabelRangeLine.calculatePointY
# Removed from Helpers
helpers.addEventhelpers.aliasPixelhelpers.arrayEqualshelpers.configMergehelpers.findIndexhelpers.findNextWherehelpers.findPreviousWherehelpers.extend. UseObject.assigninsteadhelpers.getValueAtIndexOrDefault. Usehelpers.resolveinstead.helpers.indexOfhelpers.lineTohelpers.longestTextwas made privatehelpers.maxhelpers.measureTextwas made privatehelpers.minhelpers.nextItemhelpers.niceNumhelpers.numberOfLabelLineshelpers.previousItemhelpers.removeEventhelpers.roundedRecthelpers.scaleMergehelpers.where
# Removed from Layout
Layout.defaults
# Removed from Scales
LinearScaleBase.handleDirectionalChangesLogarithmicScale.minNotZeroScale.getRightValueScale.longestLabelWidthScale.longestTextCacheis now privateScale.marginsis now privateScale.mergeTicksOptionsScale.ticksAsNumbersScale.tickValuesis now privateTimeScale.getLabelCapacityis now privateTimeScale.tickFormatFunctionis now private
# Removed from Plugins (Legend, Title, and Tooltip)
IPlugin.afterScaleUpdate. UseafterLayoutinsteadLegend.marginsis now private- Legend
onClick,onHover, andonLeaveoptions now receive the legend as the 3rd argument in addition to implicitly viathis - Legend
onClick,onHover, andonLeaveoptions now receive a wrappedeventas the first parameter. The previous first parameter value is accessible viaevent.native. Title.marginsis now private- The tooltip item's
xandyattributes were replaced byelement. You can useelement.xandelement.yorelement.tooltipPosition()instead.
# Removal of Public APIs
The following public APIs were removed.
getElementAtEventis replaced withchart.getElementsAtEventForMode(e, 'nearest', { intersect: true }, false)getElementsAtEventis replaced withchart.getElementsAtEventForMode(e, 'index', { intersect: true }, false)getElementsAtXAxisis replaced withchart.getElementsAtEventForMode(e, 'index', { intersect: false }, false)getDatasetAtEventis replaced withchart.getElementsAtEventForMode(e, 'dataset', { intersect: true }, false)
# Removal of private APIs
The following private APIs were removed.
Chart._bufferedRenderChart._updatingChart.data.datasets[datasetIndex]._metaDatasetController._getIndexScaleIdDatasetController._getIndexScaleDatasetController._getValueScaleIdDatasetController._getValueScaleElement._ctxElement._modelElement._viewLogarithmicScale._valueOffsetTimeScale.getPixelForOffsetTimeScale.getLabelWidthTooltip._lastActive
# Renamed
The following properties were renamed during v3 development:
Chart.Animation.animationObjectwas renamed toChart.AnimationChart.Animation.chartInstancewas renamed toChart.Animation.chartChart.canvasHelperswas merged withChart.helpersChart.elements.Arcwas renamed toChart.elements.ArcElementChart.elements.Linewas renamed toChart.elements.LineElementChart.elements.Pointwas renamed toChart.elements.PointElementChart.elements.Rectanglewas renamed toChart.elements.BarElementChart.layoutServicewas renamed toChart.layoutsChart.pluginServicewas renamed toChart.pluginshelpers.callCallbackwas renamed tohelpers.callbackhelpers.drawRoundedRectanglewas renamed tohelpers.roundedRecthelpers.getValueOrDefaultwas renamed tohelpers.valueOrDefaultLayoutItem.fullWidthwas renamed toLayoutItem.fullSizePoint.controlPointPreviousXwas renamed toPoint.cp1xPoint.controlPointPreviousYwas renamed toPoint.cp1yPoint.controlPointNextXwas renamed toPoint.cp2xPoint.controlPointNextYwas renamed toPoint.cp2yScale.calculateTickRotationwas renamed toScale.calculateLabelRotationTooltip.options.legendColorBackgroupdwas renamed toTooltip.options.multiKeyBackground
# Renamed private APIs
The private APIs listed below were renamed:
BarController.calculateBarIndexPixelswas renamed toBarController._calculateBarIndexPixelsBarController.calculateBarValuePixelswas renamed toBarController._calculateBarValuePixelsBarController.getStackCountwas renamed toBarController._getStackCountBarController.getStackIndexwas renamed toBarController._getStackIndexBarController.getRulerwas renamed toBarController._getRulerChart.destroyDatasetMetawas renamed toChart._destroyDatasetMetaChart.drawDatasetwas renamed toChart._drawDatasetChart.drawDatasetswas renamed toChart._drawDatasetsChart.eventHandlerwas renamed toChart._eventHandlerChart.handleEventwas renamed toChart._handleEventChart.initializewas renamed toChart._initializeChart.resetElementswas renamed toChart._resetElementsChart.unbindEventswas renamed toChart._unbindEventsChart.updateDatasetwas renamed toChart._updateDatasetChart.updateDatasetswas renamed toChart._updateDatasetsChart.updateLayoutwas renamed toChart._updateLayoutDatasetController.destroywas renamed toDatasetController._destroyDatasetController.insertElementswas renamed toDatasetController._insertElementsDatasetController.onDataPopwas renamed toDatasetController._onDataPopDatasetController.onDataPushwas renamed toDatasetController._onDataPushDatasetController.onDataShiftwas renamed toDatasetController._onDataShiftDatasetController.onDataSplicewas renamed toDatasetController._onDataSpliceDatasetController.onDataUnshiftwas renamed toDatasetController._onDataUnshiftDatasetController.removeElementswas renamed toDatasetController._removeElementsDatasetController.resyncElementswas renamed toDatasetController._resyncElementsLayoutItem.isFullWidthwas renamed toLayoutItem.isFullSizeRadialLinearScale.setReductionswas renamed toRadialLinearScale._setReductionsRadialLinearScale.pointLabelswas renamed toRadialLinearScale._pointLabelsScale.handleMarginswas renamed toScale._handleMargins
# Changed
The APIs listed in this section have changed in signature or behaviour from version 2.
# Changed in Scales
Scale.getLabelForIndexwas replaced byscale.getLabelForValueScale.getPixelForValuenow only requires one parameter. For theTimeScalethat 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.
# Changed in Ticks
Scale.afterBuildTicksnow has no parameters like the other callbacksScale.buildTicksis now expected to return tick objectsScale.convertTicksToLabelswas renamed togenerateTickLabels. It is now expected to set the label property on the ticks given as inputScale.ticksnow contains objects instead of strings- When the
autoSkipoption is enabled,Scale.ticksnow contains only the non-skipped ticks instead of all ticks. - Ticks are now always generated in monotonically increasing order
# Changed in Time Scale
getValueForPixelnow returns milliseconds since the epoch
# Changed in Controllers
# Core Controller
- The first parameter to
updateHoverStyleis now an array of objects containing theelement,datasetIndex, andindex - The signature or
resizechanged, the firstsilentparameter was removed.
# Dataset Controllers
updateElementwas replaced withupdateElementsnow taking the elements to update, thestartindex,count, andmodesetHoverStyleandremoveHoverStylenow additionally take thedatasetIndexandindex
# Changed in Interactions
- Interaction mode methods now return an array of objects containing the
element,datasetIndex, andindex
# Changed in Layout
ILayoutItem.updateno longer has a return value
# Changed in Helpers
All helpers are now exposed in a flat hierarchy, e.g., Chart.helpers.canvas.clipArea -> Chart.helpers.clipArea
# Canvas Helper
- The second parameter to
drawPointis now the full options object, sostyle,rotation, andradiusare no longer passed explicitly helpers.getMaximumHeightwas replaced byhelpers.dom.getMaximumSizehelpers.getMaximumWidthwas replaced byhelpers.dom.getMaximumSizehelpers.clearwas renamed tohelpers.clearCanvasand now takescanvasand optionallyctxas parameter(s).helpers.retinaScaleaccepts optional third parameterforceStyle, which forces overriding current canvas style.forceRationo longer falls back towindow.devicePixelRatio, instead it defaults to1.
# Changed in Platform
Chart.platformis no longer the platform object used by charts. Every chart instance now has a separate platform instance.Chart.platformsis an object that contains two usable platform classes,BasicPlatformandDomPlatform. It also containsBasePlatform, a class that all platforms must extend from.- If the canvas passed in is an instance of
OffscreenCanvas, theBasicPlatformis automatically used. isAttachedmethod was added to platform.
# Changed in IPlugin interface
- All plugin hooks have unified signature with 3 arguments:
chart,argsandoptions. 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, andbeforeUpdatenow receiveargsobject as second argument.optionsargument is always the last and thus was moved from 2nd to 3rd place.afterEventandbeforeEventnow receive a wrappedeventas theeventproperty of the second argument. The native event is available viaargs.event.native.- Initial
resizeis no longer silent. Meaning thatresizeevent can fire betweenbeforeInitandafterInit - New hooks:
install,start,stop, anduninstall afterEventshould notify about changes that need a render by settingargs.changedto true. Because theargsare shared with all plugins, it should only be set to true and not false.
← Usage Accessibility →