How do I draw horizontal bars with a label using either ChartJS or D3?

๐Ÿ‘:2

To do it with Chart.js you have to extend the line chart

Chart.types.Line.extend({
    name: "LineAlt",
    initialize: function (data) {
        // it's easier to programmatically update if you store the raw data in the object (vs. storing the geometric data)
        this.marks = data.marks;
        this.marks.xStart = Number(data.labels[0]);
        this.marks.xStep = data.labels[1] - data.labels[0];

        // make sure all our x labels are uniformly apart
        if (!data.labels.every(function (e, i, arr) { return !i || ((e - arr[i - 1]) === this.marks.xStep); }, this))
            throw "labels must be uniformly spaced";

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

        // save existing context properties
        var self = this;
        var ctx = self.chart.ctx;
        var scale = self.scale;

        ctx.save();
        // line properties
        ctx.lineWidth = 1;
        ctx.fillStyle = "#666";
        ctx.strokeStyle = "#666";
        ctx.textAlign = "center";
        ctx.textBaseline = "bottom";
        ctx.font = scale.font;

        // draw marks
        self.marks.forEach(function (mark) {
            // assuming that the marks are always within the data range
            var y = scale.calculateY(mark.y);
            var x1 = scale.calculateX((mark.x1 - self.marks.xStart) / self.marks.xStep);
            var x2 = scale.calculateX((mark.x2 - self.marks.xStart) / self.marks.xStep);

            // draw line
            ctx.beginPath();
            ctx.moveTo(x1, y);
            ctx.lineTo(x2, y);
            // draw edges
            ctx.moveTo(x1, y + 10);
            ctx.lineTo(x1, y - 10);
            ctx.moveTo(x2, y + 10);
            ctx.lineTo(x2, y - 10);
            ctx.stroke();

            // draw text
            ctx.fillText(mark.label, (x1 + x2) / 2, y + scale.fontSize * 1.5);
        })

        ctx.restore();
    },
});

You pass in the data for drawing the lines like so

var data = {
    ...
    marks: [
        {
            x1: 1.5,
            x2: 3.5,
            y: 50,
            label: 'Label1'
        },
        {
            x1: 5,
            x2: 7,
            y: 60,
            label: 'Label2'
        }
    ]
};

and you create the chart using this extended chart type

var myLineChart = new Chart(ctx).LineAlt(data);

You can update the lines like this

myLineChart.marks[0].y = 80;
myLineChart.marks[0].x1 = 9;
myLineChart.marks[0].x2 = 10;

and then call

myLineChart.update();

to reflect those changes on the canvas


Caveats

  1. The (x axis) labels should be numeric and uniformly spaced.
  2. The lines should be within the scale range of the y axis (alternatively you can do a scaleOverride to set the scale parameters so that the lines are within the y scale range)

Fiddle โ€“ http://jsfiddle.net/en92k763/2/


enter image description here

Leave a comment