Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Truncating canvas labels in ChartJS while keeping the full label value in the tooltips

I have some bar charts that have really long labels and they affect the size of the charts.

Example: http://jsfiddle.net/norbiu/aqa8w19d/4/

I'm trying to truncate the labels that show up under the chart while keeping the label that shows up in the tooltips when hovering over a bar. The problem is that the tooltips and the canvas labels both get their values from the labels array in the data structure. Truncating the value will show the shortened version in both locations.

sales: ko.observable({
    labels: ['A really really long label', 'Another long labe', 'A third label that is long', 'Q4', 'Q5', 'Q6'],
    datasets: [{
        label: 'Helados',
        fillColor: '#152491',
        data: [70, 32, 6, 23, 63, 43]
    }]
}),

The documentation has nothing on this. Any ideas?

like image 892
Norbert Avatar asked Feb 03 '15 10:02

Norbert


2 Answers

In Chart JS V2 you can truncate labels passing the options object. Also you can customize the tooltips.

options:{
    scales: {
        xAxes: [{
            ticks: {
                callback: function(value) {
                    return value.substr(0, 10);//truncate
                },
            }
        }],
        yAxes: [{}]
    },
    tooltips: {
        enabled: true,
        mode: 'label',
        callbacks: {
            title: function(tooltipItems, data) {
                var idx = tooltipItems[0].index;
                return 'Title:' + data.labels[idx];//do something with title
            },
            label: function(tooltipItems, data) {
                //var idx = tooltipItems.index;
                //return data.labels[idx] + ' €';
                return tooltipItems.xLabel + ' €';
            }
        }
    },
}
like image 162
ursuleacv Avatar answered Oct 16 '22 05:10

ursuleacv


So the way i went about this was to add a new option called labelLength which, if passed a number greater than 0, will trim the labels on the x axis to that length.

It happens in the scale class of the chart and will only apply to the axis label and not the tool tip.

If you wanted you could extract the relevant bits and just override the scale class and also the build scale function in the bar chart to include the new option.

In the scale class here is what was added

 Chart.Scale = Chart.Element.extend({
        initialize: function() {
            //truncate the labels if option is grater than 0
            this.xLabels = this.labelLength > 0 ? this.xLabels.map(this.truncateLabel, this) : this.xLabels;
            this.fit();
        },
        truncateLabel: function(label) {
            return label.substring(0, this.labelLength);
        },

        addXLabel: function(label) {
            //also added here for when adding single items of data to a graph
            this.xLabels.push(this.labelLength > 0 ? this.truncateLabel(label) : label);
            this.valuesCount++;
            this.fit();
        },

}

then in the bar buildscale function you would need to pass the option to the scale.

Or i have included this in my fork of chart js (https://github.com/leighquince/Chart.js) to use just pass the option labelLength with your desired labels length, example below

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

var barChartData = {
  labels: ["January a really long label", "February a really long label", "March a really long label", "April a really long label", "May a really long label", "June a really long label", "July a really long label"],
  datasets: [{
    fillColor: "rgba(220,220,220,0.5)",
    strokeColor: "rgba(220,220,220,0.8)",
    highlightFill: "rgba(220,220,220,0.75)",
    highlightStroke: "rgba(220,220,220,1)",
    data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()]
  }, {
    fillColor: "rgba(151,187,205,0.5)",
    strokeColor: "rgba(151,187,205,0.8)",
    highlightFill: "rgba(151,187,205,0.75)",
    highlightStroke: "rgba(151,187,205,1)",
    data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()]
  }, {
    fillColor: "rgba(15,18,20,0.5)",
    strokeColor: "rgba(15,18,20,0.8)",
    highlightFill: "rgba(15,18,20,0.75)",
    highlightStroke: "rgba(15,18,20,1)",
    data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()]
  }]

}
window.onload = function() {
  var ctx = document.getElementById("canvas").getContext("2d");
  window.myBar = new Chart(ctx).Bar(barChartData, {
    labelLength: 10,
  });
}
<script src="http://www.quincewebdesign.com/cdn/Chart.js"></script>
<div style="width: 50%">
  <canvas id="canvas" height="450" width="600"></canvas>
</div>
like image 1
Quince Avatar answered Oct 16 '22 05:10

Quince