Chartjs-How to change Y axis labels

1👍

UPDATE i’ve now added this feature into my fork of chartjs at https://github.com/leighquince/Chart.js, meanign you would not have to override or extend a new chart type. Just pass the option in like normal, here is an example http://fiddle.jshell.net/leighking2/jLzvhf4f/

So this could be achieved by overriding the scales draw method to run a custom function we provide when declaring the chart rather than just adding.

Below is the snippet but just as an explanation here is what has happened

  1. created a new chart and overridden the buildScale method to pass a new option called customYLabel. this will be the option you pass to your chart when you declare it and it has 4 parameters; the value of the label, x position, y position, the canvas, this index of the label

    1. the build scale also makes use of a custom scale
    2. create a custom scale which overrides the normal scales draw method to check for this customYLabel option and uses it if present

the reset is normal, what you customYLabel does is up to you but it should at the very least call `ctx.fillText(value,x,y) so that the label is drawn on the canvas. In the below example i colour the label based on it’s index but the options there many.

(here is a fiddle as well if thats easier to view http://fiddle.jshell.net/leighking2/2cac5t34/)

//extract helpers so we can use them in our custom scale class
var helpers = Chart.helpers,
    each = helpers.each,
    aliasPixel = helpers.aliasPixel,
    toRadians = helpers.radians;

//new line chart which has an overridden buildscale that will pass the new option customYLabel
    Chart.types.Line.extend({
        // Passing in a name registers this chart in the Chart namespace in the same way
        name: "LineAlt",
        initialize: function (data) {
            Chart.types.Line.prototype.initialize.apply(this, arguments);
        },
        buildScale: function (labels) {
            var self = this;

            var dataTotal = function () {
                var values = [];
                self.eachPoints(function (point) {
                    values.push(point.value);
                });

                return values;
            };

            var scaleOptions = {
                templateString: this.options.scaleLabel,
                height: this.chart.height,
                width: this.chart.width,
                ctx: this.chart.ctx,
                textColor: this.options.scaleFontColor,
                fontSize: this.options.scaleFontSize,
                fontStyle: this.options.scaleFontStyle,
                fontFamily: this.options.scaleFontFamily,
                valuesCount: labels.length,
                beginAtZero: this.options.scaleBeginAtZero,
                integersOnly: this.options.scaleIntegersOnly,
                //new options for custom y label
                customYLabel: this.options.customYLabel,
                calculateYRange: function (currentHeight) {
                    var updatedRanges = helpers.calculateScaleRange(
                    dataTotal(),
                    currentHeight,
                    this.fontSize,
                    this.beginAtZero,
                    this.integersOnly);
                    helpers.extend(this, updatedRanges);
                },
                xLabels: labels,
                font: helpers.fontString(this.options.scaleFontSize, this.options.scaleFontStyle, this.options.scaleFontFamily),
                lineWidth: this.options.scaleLineWidth,
                lineColor: this.options.scaleLineColor,
                showHorizontalLines: this.options.scaleShowHorizontalLines,
                showVerticalLines: this.options.scaleShowVerticalLines,
                gridLineWidth: (this.options.scaleShowGridLines) ? this.options.scaleGridLineWidth : 0,
                gridLineColor: (this.options.scaleShowGridLines) ? this.options.scaleGridLineColor : "rgba(0,0,0,0)",
                padding: (this.options.showScale) ? 0 : this.options.pointDotRadius + this.options.pointDotStrokeWidth,
                showLabels: this.options.scaleShowLabels,
                display: this.options.showScale
            };

            if (this.options.scaleOverride) {
                helpers.extend(scaleOptions, {
                    calculateYRange: helpers.noop,
                    steps: this.options.scaleSteps,
                    stepValue: this.options.scaleStepWidth,
                    min: this.options.scaleStartValue,
                    max: this.options.scaleStartValue + (this.options.scaleSteps * this.options.scaleStepWidth)
                });
            }


            this.scale = new Chart.CustomScale(scaleOptions);
        },

    });


//custom scale to use new customYLabel option
Chart.CustomScale = Chart.Scale.extend({
    draw: function () {
        var ctx = this.ctx,
            yLabelGap = (this.endPoint - this.startPoint) / this.steps,
            xStart = Math.round(this.xScalePaddingLeft);
        if (this.display) {
            ctx.fillStyle = this.textColor;
            ctx.font = this.font;
            each(this.yLabels, function (labelString, index) {
                var yLabelCenter = this.endPoint - (yLabelGap * index),
                    linePositionY = Math.round(yLabelCenter),
                    drawHorizontalLine = this.showHorizontalLines;

                ctx.textAlign = "right";
                ctx.textBaseline = "middle";
                if (this.showLabels) {
                    //if we have a customYLabel use it passing the value, x, y , canvas and index
                    if (this.customYLabel) {
                        this.customYLabel(labelString, xStart - 10, yLabelCenter, ctx, index);
                    } else {
                        ctx.fillText(labelString, xStart - 10, yLabelCenter);
                    }
                }

                // This is X axis, so draw it
                if (index === 0 && !drawHorizontalLine) {
                    drawHorizontalLine = true;
                }

                if (drawHorizontalLine) {
                    ctx.beginPath();
                }

                if (index > 0) {
                    // This is a grid line in the centre, so drop that
                    ctx.lineWidth = this.gridLineWidth;
                    ctx.strokeStyle = this.gridLineColor;
                } else {
                    // This is the first line on the scale
                    ctx.lineWidth = this.lineWidth;
                    ctx.strokeStyle = this.lineColor;
                }

                linePositionY += helpers.aliasPixel(ctx.lineWidth);

                if (drawHorizontalLine) {
                    ctx.moveTo(xStart, linePositionY);
                    ctx.lineTo(this.width, linePositionY);
                    ctx.stroke();
                    ctx.closePath();
                }

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

            }, this);

            each(this.xLabels, function (label, index) {
                var xPos = this.calculateX(index) + aliasPixel(this.lineWidth),
                    // Check to see if line/bar here and decide where to place the line
                    linePos = this.calculateX(index - (this.offsetGridLines ? 0.5 : 0)) + aliasPixel(this.lineWidth),
                    isRotated = (this.xLabelRotation > 0),
                    drawVerticalLine = this.showVerticalLines;

                // This is Y axis, so draw it
                if (index === 0 && !drawVerticalLine) {
                    drawVerticalLine = true;
                }

                if (drawVerticalLine) {
                    ctx.beginPath();
                }

                if (index > 0) {
                    // This is a grid line in the centre, so drop that
                    ctx.lineWidth = this.gridLineWidth;
                    ctx.strokeStyle = this.gridLineColor;
                } else {
                    // This is the first line on the scale
                    ctx.lineWidth = this.lineWidth;
                    ctx.strokeStyle = this.lineColor;
                }

                if (drawVerticalLine) {
                    ctx.moveTo(linePos, this.endPoint);
                    ctx.lineTo(linePos, this.startPoint - 3);
                    ctx.stroke();
                    ctx.closePath();
                }


                ctx.lineWidth = this.lineWidth;
                ctx.strokeStyle = this.lineColor;


                // Small lines at the bottom of the base grid line
                ctx.beginPath();
                ctx.moveTo(linePos, this.endPoint);
                ctx.lineTo(linePos, this.endPoint + 5);
                ctx.stroke();
                ctx.closePath();

                ctx.save();
                ctx.translate(xPos, (isRotated) ? this.endPoint + 12 : this.endPoint + 8);
                ctx.rotate(toRadians(this.xLabelRotation) * -1);
                ctx.font = this.font;
                ctx.textAlign = (isRotated) ? "right" : "center";
                ctx.textBaseline = (isRotated) ? "middle" : "top";
                ctx.fillText(label, 0, 0);
                ctx.restore();
            }, this);

        }
    }
});











var randomScalingFactor = function () {
    return Math.round(Math.random() * 100)
};

//example colour generator from 
//https://www.designedbyaturtle.co.uk/2014/convert-string-to-hexidecimal-colour-with-javascript-vanilla/

// Convert an int to hexadecimal with a max length
// of six characters.
var intToARGB = function (i) {
    var h = ((i >> 24) & 0xFF).toString(16) + ((i >> 16) & 0xFF).toString(16) + ((i >> 8) & 0xFF).toString(16) + (i & 0xFF).toString(16);
    return h.substring(0, 6);
}
var lineChartData = {
    labels: ["January", "February", "March", "April", "May", "June", "July"],
    datasets: [{
        label: "My First dataset",
        fillColor: "rgba(220,220,220,0.2)",
        strokeColor: "rgba(220,220,220,1)",
        pointColor: "rgba(220,220,220,1)",
        pointStrokeColor: "#fff",
        pointHighlightFill: "#fff",
        pointHighlightStroke: "rgba(220,220,220,1)",
        data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()]

    }, {
        label: "My Second dataset",
        fillColor: "rgba(151,187,205,0.2)",
        strokeColor: "rgba(151,187,205,1)",
        pointColor: "rgba(151,187,205,1)",
        pointStrokeColor: "#fff",
        pointHighlightFill: "#fff",
        pointHighlightStroke: "rgba(151,187,205,1)",
        data: [null, 10, null, null, 60, null, null]

    }]

}


var ctx = document.getElementById("canvas").getContext("2d");
window.myLine = new Chart(ctx).LineAlt(lineChartData, {
    //example of how this can be used, could use the value instead of the index
    customYLabel: function (value, x, y, ctx, index) {
        var defaultStyle = ctx.fillStyle;
        ctx.fillStyle = '#' + intToARGB(index * 123456);
        ctx.fillText(value, x, y);
        ctx.fillStyle = defaultStyle;
    }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/1.0.1/Chart.js"></script>
<div style="width:100%">
    <div>
        <canvas id="canvas" height="200" width="600"></canvas>
    </div>
</div>

Leave a comment