# 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.js
andChart.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 thetime
ortimeseries
scales, 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
Chart
constructor 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
npm
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 callregister
if importing Chart.js via ascript
tag or from theauto
register path as annpm
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'
}
}
}
})
# Chart types
horizontalBar
chart type was removed. Horizontal bar charts can be configured using the newindexAxis
option
# 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.rectangle
is nowelements.bar
hover.animationDuration
is now configured inanimation.active.duration
responsiveAnimationDuration
is now configured inanimation.resize.duration
- Polar area
elements.arc.angle
is now configured in degrees instead of radians. - Polar area
startAngle
option is now consistent withRadar
, 0 is at top and value is in degrees. Default is changed from-½π
to0
. - Doughnut
rotation
option is now in degrees and 0 is at top. Default is changed from-½π
to0
. - Doughnut
circumference
option is now in degrees. Default is changed from2π
to360
. - Doughnut
cutoutPercentage
was renamed tocutout
and accepts pixels as number and percent as string ending with%
. scale
option was removed in favor ofoptions.scales.r
(or any other scale id, withaxis: 'r'
)scales.[x/y]Axes
arrays were removed. Scales are now configured directly tooptions.scales
object with the object key being the scale Id.scales.[x/y]Axes.barPercentage
was moved to dataset optionbarPercentage
scales.[x/y]Axes.barThickness
was moved to dataset optionbarThickness
scales.[x/y]Axes.categoryPercentage
was moved to dataset optioncategoryPercentage
scales.[x/y]Axes.maxBarThickness
was moved to dataset optionmaxBarThickness
scales.[x/y]Axes.minBarLength
was moved to dataset optionminBarLength
scales.[x/y]Axes.scaleLabel
was renamed toscales[id].title
scales.[x/y]Axes.scaleLabel.labelString
was renamed toscales[id].title.text
scales.[x/y]Axes.ticks.beginAtZero
was renamed toscales[id].beginAtZero
scales.[x/y]Axes.ticks.max
was renamed toscales[id].max
scales.[x/y]Axes.ticks.min
was renamed toscales[id].min
scales.[x/y]Axes.ticks.reverse
was renamed toscales[id].reverse
scales.[x/y]Axes.ticks.suggestedMax
was renamed toscales[id].suggestedMax
scales.[x/y]Axes.ticks.suggestedMin
was renamed toscales[id].suggestedMin
scales.[x/y]Axes.ticks.unitStepSize
was removed. Usescales[id].ticks.stepSize
scales.[x/y]Axes.ticks.userCallback
was renamed toscales[id].ticks.callback
scales.[x/y]Axes.time.format
was renamed toscales[id].time.parser
scales.[x/y]Axes.time.max
was renamed toscales[id].max
scales.[x/y]Axes.time.min
was renamed toscales[id].min
scales.[x/y]Axes.zeroLine*
options of axes were removed. Use scriptable scale options instead.- The dataset option
steppedLine
was removed. Usestepped
- The chart option
showLines
was renamed toshowLine
to match the dataset option. - The chart option
startAngle
was moved toradial
scale options. - To override the platform class used in a chart instance, pass
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 readt
from object data by default anymore. The default property isx
ory
, depending on the orientation. See data structures for details on how to change the default.tooltips
namespace was renamed totooltip
to match the plugin namelegend
,title
andtooltip
namespaces were moved fromoptions
tooptions.plugins
.tooltips.custom
was renamed toplugins.tooltip.external
# Defaults
global
namespace was removed fromdefaults
. SoChart.defaults.global
is nowChart.defaults
- Dataset controller defaults were relocate to
overrides
. For exampleChart.defaults.line
is nowChart.overrides.line
default
prefix was removed from defaults. For exampleChart.defaults.global.defaultColor
is nowChart.defaults.color
defaultColor
was split tocolor
,borderColor
andbackgroundColor
defaultFontColor
was renamed tocolor
defaultFontFamily
was renamed tofont.family
defaultFontSize
was renamed tofont.size
defaultFontStyle
was renamed tofont.style
defaultLineHeight
was renamed tofont.lineHeight
- Horizontal Bar default tooltip mode was changed from
'index'
to'nearest'
to match vertical bar charts legend
,title
andtooltip
namespaces were moved fromChart.defaults
toChart.defaults.plugins
.elements.line.fill
default changed fromtrue
tofalse
.- Line charts no longer override the default
interaction
mode. 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 typetimeseries
was introduced in its place - In the time scale,
autoSkip
is 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
custom
attribute of elements was removed. Please use scriptable options- The
hover
property of scriptable optionscontext
object was renamed toactive
to align it with the datalabels plugin.
# Interactions
- To allow DRY configuration, a root options scope for common interaction options was added.
options.hover
andoptions.plugins.tooltip
now both extend fromoptions.interaction
. Defaults are defined atdefaults.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
andoptions.onHover
now receive thechart
instance as a 3rd argumentoptions.onHover
now receives a wrappedevent
as the first parameter. The previous first parameter value is accessible viaevent.native
.options.hover.onHover
was removed, useoptions.onHover
.
# Ticks
options.gridLines
was renamed tooptions.grid
options.gridLines.offsetGridLines
was renamed tooptions.grid.offset
.options.gridLines.tickMarkLength
was renamed tooptions.grid.tickLength
.options.ticks.fixedStepSize
is no longer used. Useoptions.ticks.stepSize
.options.ticks.major
andoptions.ticks.minor
were replaced with scriptable options for tick fonts.Chart.Ticks.formatters.linear
was renamed toChart.Ticks.formatters.numeric
.options.ticks.backdropPaddingX
andoptions.ticks.backdropPaddingY
were replaced withoptions.ticks.backdropPadding
in the radial linear scale.
# Tooltip
xLabel
andyLabel
were removed. Please uselabel
andformattedValue
- The
filter
option will now be passed additional parameters when called and should have the method signaturefunction(tooltipItem, index, tooltipItems, data)
- The
custom
callback now takes a context object that hastooltip
andchart
properties - All properties of tooltip model related to the tooltip options have been moved to reside within the
options
property. - The callbacks no longer are given a
data
parameter. The tooltip item parameter contains the chart and dataset instead - The tooltip item's
index
parameter was renamed todataIndex
andvalue
was renamed toformattedValue
- The
xPadding
andyPadding
options were merged into a singlepadding
object
# 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 Discord (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._model
andElement._view
are no longer used and properties are now set directly on the elements. You will have to use the methodgetProps
to access these properties inside most methods such asinXRange
/inYRange
andgetCenterPoint
. 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
updateElement
to provide the element properties. There are also methods such asgetSharedOptions
andincludeOptions
that 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
string
and converts it to anumber
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 likex
/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 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:
global
was 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.
x
instead ofxAxes
andy
instead ofyAxes
)
updateElement
was changed toupdateElements
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 calls
# Removed
The following properties and methods were removed:
# Removed from Chart
Chart.animationService
Chart.active
Chart.borderWidth
Chart.chart.chart
Chart.Bar
. New charts are created vianew Chart
and providing the appropriatetype
parameterChart.Bubble
. New charts are created vianew Chart
and providing the appropriatetype
parameterChart.Chart
Chart.Controller
Chart.Doughnut
. New charts are created vianew Chart
and providing the appropriatetype
parameterChart.innerRadius
now lives on doughnut, pie, and polarArea controllersChart.lastActive
Chart.Legend
was moved toChart.plugins.legend._element
and made privateChart.Line
. New charts are created vianew Chart
and providing the appropriatetype
parameterChart.LinearScaleBase
now must be imported and cannot be accessed off theChart
objectChart.offsetX
Chart.offsetY
Chart.outerRadius
now lives on doughnut, pie, and polarArea controllersChart.plugins
was replaced withChart.registry
. Plugin defaults are now inChart.defaults.plugins[id]
.Chart.plugins.register
was replaced byChart.register
.Chart.PolarArea
. New charts are created vianew Chart
and providing the appropriatetype
parameterChart.prototype.generateLegend
Chart.platform
. It only containeddisableCSSInjection
. CSS is never injected in v3.Chart.PluginBase
Chart.Radar
. New charts are created vianew Chart
and providing the appropriatetype
parameterChart.radiusLength
Chart.scaleService
was replaced withChart.registry
. Scale defaults are now inChart.defaults.scales[type]
.Chart.Scatter
. New charts are created vianew Chart
and providing the appropriatetype
parameterChart.types
Chart.Title
was moved toChart.plugins.title._element
and made privateChart.Tooltip
is now provided by the tooltip plugin. The positioners can be accessed fromtooltipPlugin.positioners
ILayoutItem.minSize
# Removed from Dataset Controllers
BarController.getDatasetMeta().bar
DatasetController.addElementAndReset
DatasetController.createMetaData
DatasetController.createMetaDataset
DoughnutController.getRingIndex
# Removed from Elements
Element.getArea
Element.height
Element.hidden
was replaced by chart level status, usable withgetDataVisibility(index)
/toggleDataVisibility(index)
Element.initialize
Element.inLabelRange
Line.calculatePointY
# Removed from Helpers
helpers.addEvent
helpers.aliasPixel
helpers.arrayEquals
helpers.configMerge
helpers.findIndex
helpers.findNextWhere
helpers.findPreviousWhere
helpers.extend
. UseObject.assign
insteadhelpers.getValueAtIndexOrDefault
. Usehelpers.resolve
instead.helpers.indexOf
helpers.lineTo
helpers.longestText
was made privatehelpers.max
helpers.measureText
was made privatehelpers.min
helpers.nextItem
helpers.niceNum
helpers.numberOfLabelLines
helpers.previousItem
helpers.removeEvent
helpers.roundedRect
helpers.scaleMerge
helpers.where
# Removed from Layout
Layout.defaults
# Removed from Scales
LinearScaleBase.handleDirectionalChanges
LogarithmicScale.minNotZero
Scale.getRightValue
Scale.longestLabelWidth
Scale.longestTextCache
is now privateScale.margins
is now privateScale.mergeTicksOptions
Scale.ticksAsNumbers
Scale.tickValues
is now privateTimeScale.getLabelCapacity
is now privateTimeScale.tickFormatFunction
is now private
# Removed from Plugins (Legend, Title, and Tooltip)
IPlugin.afterScaleUpdate
. UseafterLayout
insteadLegend.margins
is now private- Legend
onClick
,onHover
, andonLeave
options now receive the legend as the 3rd argument in addition to implicitly viathis
- Legend
onClick
,onHover
, andonLeave
options now receive a wrappedevent
as the first parameter. The previous first parameter value is accessible viaevent.native
. Title.margins
is now private- The tooltip item's
x
andy
attributes were replaced byelement
. You can useelement.x
andelement.y
orelement.tooltipPosition()
instead.
# Removal of Public APIs
The following public APIs were removed.
getElementAtEvent
is replaced withchart.getElementsAtEventForMode(e, 'nearest', { intersect: true }, false)
getElementsAtEvent
is replaced withchart.getElementsAtEventForMode(e, 'index', { intersect: true }, false)
getElementsAtXAxis
is replaced withchart.getElementsAtEventForMode(e, 'index', { intersect: false }, false)
getDatasetAtEvent
is replaced withchart.getElementsAtEventForMode(e, 'dataset', { intersect: true }, false)
# Removal of private APIs
The following private APIs were removed.
Chart._bufferedRender
Chart._updating
Chart.data.datasets[datasetIndex]._meta
DatasetController._getIndexScaleId
DatasetController._getIndexScale
DatasetController._getValueScaleId
DatasetController._getValueScale
Element._ctx
Element._model
Element._view
LogarithmicScale._valueOffset
TimeScale.getPixelForOffset
TimeScale.getLabelWidth
Tooltip._lastActive
# Renamed
The following properties were renamed during v3 development:
Chart.Animation.animationObject
was renamed toChart.Animation
Chart.Animation.chartInstance
was renamed toChart.Animation.chart
Chart.canvasHelpers
was merged withChart.helpers
Chart.elements.Arc
was renamed toChart.elements.ArcElement
Chart.elements.Line
was renamed toChart.elements.LineElement
Chart.elements.Point
was renamed toChart.elements.PointElement
Chart.elements.Rectangle
was renamed toChart.elements.BarElement
Chart.layoutService
was renamed toChart.layouts
Chart.pluginService
was renamed toChart.plugins
helpers.callCallback
was renamed tohelpers.callback
helpers.drawRoundedRectangle
was renamed tohelpers.roundedRect
helpers.getValueOrDefault
was renamed tohelpers.valueOrDefault
LayoutItem.fullWidth
was renamed toLayoutItem.fullSize
Point.controlPointPreviousX
was renamed toPoint.cp1x
Point.controlPointPreviousY
was renamed toPoint.cp1y
Point.controlPointNextX
was renamed toPoint.cp2x
Point.controlPointNextY
was renamed toPoint.cp2y
Scale.calculateTickRotation
was renamed toScale.calculateLabelRotation
Tooltip.options.legendColorBackgroupd
was renamed toTooltip.options.multiKeyBackground
# Renamed private APIs
The private APIs listed below were renamed:
BarController.calculateBarIndexPixels
was renamed toBarController._calculateBarIndexPixels
BarController.calculateBarValuePixels
was renamed toBarController._calculateBarValuePixels
BarController.getStackCount
was renamed toBarController._getStackCount
BarController.getStackIndex
was renamed toBarController._getStackIndex
BarController.getRuler
was renamed toBarController._getRuler
Chart.destroyDatasetMeta
was renamed toChart._destroyDatasetMeta
Chart.drawDataset
was renamed toChart._drawDataset
Chart.drawDatasets
was renamed toChart._drawDatasets
Chart.eventHandler
was renamed toChart._eventHandler
Chart.handleEvent
was renamed toChart._handleEvent
Chart.initialize
was renamed toChart._initialize
Chart.resetElements
was renamed toChart._resetElements
Chart.unbindEvents
was renamed toChart._unbindEvents
Chart.updateDataset
was renamed toChart._updateDataset
Chart.updateDatasets
was renamed toChart._updateDatasets
Chart.updateLayout
was renamed toChart._updateLayout
DatasetController.destroy
was renamed toDatasetController._destroy
DatasetController.insertElements
was renamed toDatasetController._insertElements
DatasetController.onDataPop
was renamed toDatasetController._onDataPop
DatasetController.onDataPush
was renamed toDatasetController._onDataPush
DatasetController.onDataShift
was renamed toDatasetController._onDataShift
DatasetController.onDataSplice
was renamed toDatasetController._onDataSplice
DatasetController.onDataUnshift
was renamed toDatasetController._onDataUnshift
DatasetController.removeElements
was renamed toDatasetController._removeElements
DatasetController.resyncElements
was renamed toDatasetController._resyncElements
LayoutItem.isFullWidth
was renamed toLayoutItem.isFullSize
RadialLinearScale.setReductions
was renamed toRadialLinearScale._setReductions
RadialLinearScale.pointLabels
was renamed toRadialLinearScale._pointLabels
Scale.handleMargins
was renamed toScale._handleMargins
# Changed
The APIs listed in this section have changed in signature or behaviour from version 2.
# Changed in Scales
Scale.getLabelForIndex
was replaced byscale.getLabelForValue
Scale.getPixelForValue
now only requires one parameter. For theTimeScale
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.
# Changed in Ticks
Scale.afterBuildTicks
now has no parameters like the other callbacksScale.buildTicks
is now expected to return tick objectsScale.convertTicksToLabels
was renamed togenerateTickLabels
. It is now expected to set the label property on the ticks given as inputScale.ticks
now contains objects instead of strings- When the
autoSkip
option is enabled,Scale.ticks
now contains only the non-skipped ticks instead of all ticks. - Ticks are now always generated in monotonically increasing order
# Changed in Time Scale
getValueForPixel
now returns milliseconds since the epoch
# Changed in Controllers
# Core Controller
- The first parameter to
updateHoverStyle
is now an array of objects containing theelement
,datasetIndex
, andindex
- The signature or
resize
changed, the firstsilent
parameter was removed.
# Dataset Controllers
updateElement
was replaced withupdateElements
now taking the elements to update, thestart
index,count
, andmode
setHoverStyle
andremoveHoverStyle
now additionally take thedatasetIndex
andindex
# Changed in Interactions
- Interaction mode methods now return an array of objects containing the
element
,datasetIndex
, andindex
# Changed in Layout
ILayoutItem.update
no 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
drawPoint
is now the full options object, sostyle
,rotation
, andradius
are no longer passed explicitly helpers.getMaximumHeight
was replaced byhelpers.dom.getMaximumSize
helpers.getMaximumWidth
was replaced byhelpers.dom.getMaximumSize
helpers.clear
was renamed tohelpers.clearCanvas
and now takescanvas
and optionallyctx
as parameter(s).helpers.retinaScale
accepts optional third parameterforceStyle
, which forces overriding current canvas style.forceRatio
no longer falls back towindow.devicePixelRatio
, instead it defaults to1
.
# Changed in Platform
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
andDomPlatform
. It also containsBasePlatform
, a class that all platforms must extend from.- If the canvas passed in is an instance of
OffscreenCanvas
, theBasicPlatform
is automatically used. isAttached
method was added to platform.
# Changed in IPlugin interface
- All plugin hooks have unified signature with 3 arguments:
chart
,args
andoptions
. 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
, andbeforeUpdate
now receiveargs
object as second argument.options
argument is always the last and thus was moved from 2nd to 3rd place.afterEvent
andbeforeEvent
now receive a wrappedevent
as theevent
property of the second argument. The native event is available viaargs.event.native
.- Initial
resize
is no longer silent. Meaning thatresize
event can fire betweenbeforeInit
andafterInit
- New hooks:
install
,start
,stop
, anduninstall
afterEvent
should notify about changes that need a render by settingargs.changed
to true. Because theargs
are shared with all plugins, it should only be set to true and not false.