Mars Robertson
Mars Robertson

Reputation: 13213

ChartJS - how to display line chart with single element as a line? (not as a dot)

I'm using: http://www.chartjs.org/docs/#chart-configuration-mixed-chart-types + AngularJS wrapper: http://jtblin.github.io/angular-chart.js/

When creating a chart, you have the option to overlay different chart types on top of each other as separate datasets.

To do this, you must set a type for each dataset individually. You can create mixed chart types with bar and line chart types.

When creating the chart you must set the overall type as bar.

There is a slight difference how lines are presented - if I display bar and line on the same graph, the line does not go to an end.

enter image description here

It doesn't really matter that much, unless I have single element only... enter image description here

ChartJS displays line charts with single element as a dot - Chartjs linechart with only one point - how to center (and they suggest added some null elements, I'm not sure if I want to follow that route)

Here some example how to draw vertical line on canvas: http://jsfiddle.net/zk9oc4c9/ (feels like too much effort calculating everything manually)

Codepen: http://codepen.io/stefek99/pen/WpRQgp?editors=1010

Maybe there is a better way?

enter image description here

Upvotes: 5

Views: 6323

Answers (2)

Mars Robertson
Mars Robertson

Reputation: 13213

This helped me a lot: How to draw Horizontal line on Bar Chart Chartjs

Here is the working demo: http://codepen.io/stefek99/pen/ZeXzBr?editors=1010

Defining a plugin:

Chart.pluginService.register({
    afterDraw: function(chart) {

        if (typeof chart.config.options.lineAt != 'undefined') {
            var lineAt = chart.config.options.lineAt;
            var ctxPlugin = chart.chart.ctx;
            var xAxe = chart.scales[chart.config.options.scales.xAxes[0].id];
            var yAxe = chart.scales[chart.config.options.scales.yAxes[0].id];

            var position = yAxe.getPixelForValue(lineAt)

            ctxPlugin.strokeStyle = "red";
            ctxPlugin.beginPath();
            ctxPlugin.moveTo(xAxe.left, position);
            ctxPlugin.lineTo(xAxe.right, position);
            ctxPlugin.stroke();
        }
    }
});

Checking if the line is required

var _drawLineOnTopOfADot = function(chartData) {
  if (chartData.labels.length !== 1) return; // only handling graphs that have single item
  if (chartData.dataSetOverride.length < 2) return; // only when we have at least two types of graph
  var indexOfLineGraph = -1;
  for (var i=0; i<chartData.dataSetOverride.length; i++) {
    if (chartData.dataSetOverride[i].type === "line") {
      indexOfLineGraph = i;
      break;
    }
  }
  if (indexOfLineGraph === -1) return; // no line chart, no worries

  chartData.options = chartData.options || {};
  chartData.options.lineAt = chartData.data[indexOfLineGraph][0]; 
}

I've spent way too much time on that.

Upvotes: 3

jordanwillis
jordanwillis

Reputation: 10705

In addition to the options that you found, you could use the chart.js annotation plugin to easily draw your line without having to mess with rendering pixels in your canvas manually. Note, the plugin is created/supported by the same team as chart.js and is mentioned in the chart.js docs.

Here is an example codepen demonstrating your scenario.

Once you add the plugin, you simply just set additional properties in your chart config.

var myChart = new Chart(ctx, {
  type: 'line',
  data: {
    labels: ["January"],
    datasets: [{
      label: 'Dataset 1',
      borderColor: window.chartColors.blue,
      borderWidth: 2,
      fill: false,
      data: [5]
    }]
  },
  options: {
    responsive: true,
    title: {
      display: true,
      text: 'Chart.js Stacked Bar and Unstacked Line Combo Chart'
    },
    tooltips: {
      mode: 'index',
      intersect: true
    },
    annotation: {
      annotations: [{
        type: 'line',
        mode: 'horizontal',
        scaleID: 'y-axis-0',
        value: 5,
        borderColor: 'rgb(75, 192, 192)',
        borderWidth: 4,
        label: {
          enabled: false,
          content: 'Test label'
        }
      }]
    }
  }
});

This is still a little cumbersome because you have you define the location of the line separate from your data point value, but its certainly easier then the other approach.

I'm not sure if there is an existing angular extension of the plugin, but I assume you can create one easy enough if need be.

Upvotes: 1

Related Questions