Accepted answer

There are three things that need to be done to support this feature:

  1. Use the category scale to calculate bar thickness in proportion to axis size (width for vertical, height for horizontal)
  2. Override the #getPixelForValue() method in the category scale so that the category widths reflect the variant thickness, instead of being uniform
  3. Change the dimensions of the rectangles drawn by the controller using the values calculated by the scale

Implemented these as a custom chart in this package: using Chart.js's new chart and new axes customization features.

Solved (1) by adding behavior like this to the category scale:

getBarThickness(thicknessPercentage) {
  let thickness = thicknessPercentage * this._axisSize(),
    spacing = this.options.spacing * 2

  return thickness - spacing

_axisSize() {
  return this.isHorizontal() ? this.width : this.height

(2) is a bit more complicated because the pixel for each value in the category scale needs to take into account all of the various thicknesses for each previous item in the dataset when calculating the distance from the edge (left for horizontal, or top for vertical). Otherwise the thicknesses of the categories in the axis will not match the thicknesses of the bars, and the category axis labels will not be centered on the bars.

Relevant file for (1) and (2):

(3) is solved by changing the relevant dimension in the element's _view and _model properties using the Scale#getBarThickness() method above.

Relevant file for (3):

Figured most of this out by reading the source code for Chart.js, especially scale.category.js and core.datasetController.js. Also took some inspiration from the source code for Chart.smith.js.

Related Query

More Query from same tag