23

I would like to draw a horizontal line in a chart using Chart.js. But I'm not able to do it.

I've read this question - Chart.js — drawing an arbitrary vertical line - but I can't transform the code for drawing horizontal lines not vertical.

I hope you can help me (especially potatopeelings :)).

Tim Gautier
  • 29,150
  • 5
  • 46
  • 53
KRiSTiN
  • 429
  • 1
  • 4
  • 11
  • 1
    How is it that all these answers suck? They have the wrong version or are horrifically documented. Can't believe that it's so complex – Anthony Dec 29 '18 at 04:55
  • Here you are going to find code and JS fiddle for [Chartjs2+](https://stackoverflow.com/a/39206852/5119682) – Xxx Xxx Sep 04 '19 at 14:11

5 Answers5

17

Here is the JavaScript code to draw a horizontal line.

var data = {
    labels: ["JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC"],
    datasets: [{
        data: [12, 3, 2, 1, 8, 8, 2, 2, 3, 5, 7, 1]
    }]
};

var ctx = document.getElementById("LineWithLine").getContext("2d");

Chart.types.Line.extend({
    name: "LineWithLine",
    initialize: function () {
        Chart.types.Line.prototype.initialize.apply(this, arguments);
    },
    draw: function () {
        Chart.types.Line.prototype.draw.apply(this, arguments);

        var point = this.datasets[0].points[this.options.lineAtIndex]
        var scale = this.scale
        console.log(this);

        // draw line
        this.chart.ctx.beginPath();
        this.chart.ctx.moveTo(scale.startPoint+12, point.y);
        this.chart.ctx.strokeStyle = '#ff0000';
        this.chart.ctx.lineTo(this.chart.width, point.y);
        this.chart.ctx.stroke();

        // write TODAY
        this.chart.ctx.textAlign = 'center';
        this.chart.ctx.fillText("TODAY", scale.startPoint + 35, point.y+10);
    }
});

new Chart(ctx).LineWithLine(data, {
    datasetFill : false,
    lineAtIndex: 2
});

http://jsfiddle.net/7a4hhzge/455/

This is based off of the code used to draw an arbitrary vertical line, it may not be perfect but you should be able to adjust it to fit your needs.

Tim Gautier
  • 29,150
  • 5
  • 46
  • 53
Jacob
  • 2,769
  • 3
  • 21
  • 29
  • Thanks! Everything works. But do you know how to change the code to set value, where the line should be displayed, not only points? – KRiSTiN Jun 27 '15 at 20:51
16

Without any additional code, I managed to draw a line by adding a new entry as a dataset with these options :

Just replace with the size of your dataset, and with the value that the line represents.

{
  data: Array.apply(null, new Array(<length>)).map(Number.prototype.valueOf, <value>),
  fill: false,
  radius: 0,
  backgroundColor: "rgba(0,0,0,0.1)"
}

The radius of 0 will somehow hide the dots and the fill: false will make it appear as a line.

Julien Ricard
  • 316
  • 2
  • 11
5

If you need many lines with certain Y value, try this code

var data = {
    labels: ["JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC"],
    datasets: [{
        data: [12, 3, 2, 1, 8, 8, 2, 2, 3, 5, 7, 1]
    }]
};

var ctx = document.getElementById("LineWithLine").getContext("2d");

Chart.types.Line.extend({
    name: "LineWithLine",
    draw: function () {
        Chart.types.Line.prototype.draw.apply(this, arguments);

        var lines = this.options.limitLines;

        for (var i = lines.length; --i >= 0;) {

            var xStart = Math.round(this.scale.xScalePaddingLeft);
            var linePositionY = this.scale.calculateY(lines[i].value);

            this.chart.ctx.fillStyle = lines[i].color ? lines[i].color : this.scale.textColor;
            this.chart.ctx.font = this.scale.font;
            this.chart.ctx.textAlign = "left";
            this.chart.ctx.textBaseline = "top";

            if (this.scale.showLabels && lines[i].label) {
                this.chart.ctx.fillText(lines[i].label, xStart + 5, linePositionY);
            }

            this.chart.ctx.lineWidth = this.scale.gridLineWidth;
            this.chart.ctx.strokeStyle = lines[i].color ? lines[i].color : this.scale.gridLineColor;

            if (this.scale.showHorizontalLines) {
                this.chart.ctx.beginPath();
                this.chart.ctx.moveTo(xStart, linePositionY);
                this.chart.ctx.lineTo(this.scale.width, linePositionY);
                this.chart.ctx.stroke();
                this.chart.ctx.closePath();
            }

            this.chart.ctx.lineWidth = this.lineWidth;
            this.chart.ctx.strokeStyle = this.lineColor;
            this.chart.ctx.beginPath();
            this.chart.ctx.moveTo(xStart - 5, linePositionY);
            this.chart.ctx.lineTo(xStart, linePositionY);
            this.chart.ctx.stroke();
            this.chart.ctx.closePath();
        }
    }
});

new Chart(ctx).LineWithLine(data, {
    datasetFill : false,
    limitLines: [
        {
            label: 'max',
            value: 17,
            color: 'rgba(255, 0, 0, .8)'
        },
        {
            label: 'min',
            value: 1
        },
        {
            value: 7,
            color: 'rgba(0, 255, 255, .8)'
        }
    ],
});

http://jsfiddle.net/vsh6tcfd/3/

dFelinger
  • 97
  • 1
  • 8
3

Based on dFelinger message I made a new char type that draws an average line on the line chart. Here's the code, just copy and call a new chart with the new type called 'lineWithAverage' WORKS ONLY FOR CHARTJS 2

    Chart.controllers.lineWithAverage = Chart.controllers.line.extend({
        initialize: function () {
            Chart.controllers.line.prototype.initialize.apply(this, arguments);
        },
        draw: function () {
            Chart.controllers.line.prototype.draw.apply(this, arguments);

            var scale = this.scale
            var sum = 0;
            this.getDataset().data.forEach(function(value) {
              sum = sum + value;
            });

            var average = sum / this.getDataset().data.length;

            var averageCoord = this.calculatePointY(average);

            // draw line
            this.chart.chart.canvas.ctx = this.chart.chart.canvas.getContext('2d');
            this.chart.chart.canvas.ctx.beginPath();
            this.chart.chart.canvas.ctx.moveTo(0, averageCoord);
            this.chart.chart.canvas.ctx.strokeStyle = '#979797';
            this.chart.chart.canvas.ctx.lineTo(this.chart.chart.width, averageCoord);
            this.chart.chart.canvas.ctx.stroke();
        }
    });
1

The simplest way I've found to create a horizontal line was by just creating a new dataset with every entry set to some constant value (y = 75 for example). Then I set pointRadius and pointHitRadius to zero to hide the tooltips and points on the graph.

datasets: [
  {
    data: your_data,
    ...
  },
  {
    data: your_data.map(r => 75),
    pointRadius: 0,
    pointHitRadius: 0,
  },
]
spencer.sm
  • 19,173
  • 10
  • 77
  • 88