[Chartjs]-Is it able to align line chart at left margin in mixed chart?

1👍

There is no way to do this purely by configuration in chart.js. After browsing through the source, I see that line charts get set with a offset = true property internally when they appear on a combo bar chart.

Therefore, the only way to achieve this behavior is to extend the line chart and implement your own function to control the setting of this offset variable. It turns out it’s not that difficult to do. Here is an example (note, the offset variable is only set in the line chart’s updateElement() function).

var helpers = Chart.helpers;

Chart.controllers.LineNoOffset = Chart.controllers.line.extend({
  updateElement: function(point, index, reset) {
    var me = this;
    var meta = me.getMeta();
    var custom = point.custom || {};
    var dataset = me.getDataset();
    var datasetIndex = me.index;
    var value = dataset.data[index];
    var yScale = me.getScaleForId(meta.yAxisID);
    var xScale = me.getScaleForId(meta.xAxisID);
    var pointOptions = me.chart.options.elements.point;
    var x, y;
    var labels = me.chart.data.labels || [];
    var includeOffset = false;

    // Compatibility: If the properties are defined with only the old name, use those values
    if ((dataset.radius !== undefined) && (dataset.pointRadius === undefined)) {
      dataset.pointRadius = dataset.radius;
    }
    if ((dataset.hitRadius !== undefined) && (dataset.pointHitRadius === undefined)) {
      dataset.pointHitRadius = dataset.hitRadius;
    }

    x = xScale.getPixelForValue(typeof value === 'object' ? value : NaN, index, datasetIndex, includeOffset);
    y = reset ? yScale.getBasePixel() : me.calculatePointY(value, index, datasetIndex);

    // Utility
    point._xScale = xScale;
    point._yScale = yScale;
    point._datasetIndex = datasetIndex;
    point._index = index;

    // Desired view properties
    point._model = {
      x: x,
      y: y,
      skip: custom.skip || isNaN(x) || isNaN(y),
      // Appearance
      radius: custom.radius || helpers.getValueAtIndexOrDefault(dataset.pointRadius, index, pointOptions.radius),
      pointStyle: custom.pointStyle || helpers.getValueAtIndexOrDefault(dataset.pointStyle, index, pointOptions.pointStyle),
      backgroundColor: me.getPointBackgroundColor(point, index),
      borderColor: me.getPointBorderColor(point, index),
      borderWidth: me.getPointBorderWidth(point, index),
      tension: meta.dataset._model ? meta.dataset._model.tension : 0,
      steppedLine: meta.dataset._model ? meta.dataset._model.steppedLine : false,
      // Tooltip
      hitRadius: custom.hitRadius || helpers.getValueAtIndexOrDefault(dataset.pointHitRadius, index, pointOptions.hitRadius)
    };
  },
});

Once your new chart type is defined, then you have to change your configuration to use this new type.

Here is a codepen example showing the final result (and demonstrating how to do this).

4👍

Based on the answer by @jordanwillis I figured out a bit better method, that is compatible with chart.js 2.7.* , and should be more safe to use with future versions, because it reuses more of existing code:

Chart.controllers.LineNoOffset = Chart.controllers.line.extend({
    updateElement: function(point, index, reset) {
        Chart.controllers.line.prototype.updateElement.call(this, point, index, reset);
        const meta = this.getMeta();
        const xScale = this.getScaleForId(meta.xAxisID);
        point._model.x = xScale.getPixelForValue(undefined, index-0.5);
    },
});

Leave a comment