简体   繁体   中英

ChartJS v3.X - Limit the string size of label on canvas, without changing tooltip hover string

So, I had some old charts code using a very old Chart.js version 2.x but now due to the need of some functions only found on versions 3.x I'm updating a lot of code from the old charts on the website because a lot of the syntax changed between versions.

I just finished updating all charts and they are working nicely using plugins and etc, except for one.

On this type: 'bar' chart I have some very long strings on the 'X' axis, so I need to trim them to a max of 12 characters, but the tooltips need to show the whole string. The old code used to be this one and worked like a charm, right before rendering the chart I would set the updateScaleDefaults:

// Limit the size of label for 12 characters, tooltip on hover not changed
Chart.scaleService.updateScaleDefaults('category', {  
            ticks: {
            callback: function(tick) {
                var characterLimit = 12;
                if ( tick.length >= characterLimit) {
                    return tick.slice(0, tick.length).substring(0, characterLimit -1).trim() + '...';;
                }
                return tick;
                }
            }
});

So right after that I would call the new Chart instance and would render it on a canvas. But now this code doesn't work anymore on v3.x, and I can't make an alternative version of this work.

As the migration guide for V3.x states on the documentation ,

Chart.scaleService was replaced with Chart.registry . Scale defaults are now in Chart.defaults.scales[type]

So I tried changing the first line of the code above to this and many other variations, trying to reuse the old code just changing the call to the object:

Chart.defaults.scales['category']

Nothing I tried worked.

I then tried creating a plugin with an beforeDraw , acessing the chart.scales.x.ticks and trying to make an arrow function on a map call, but I got a $context is a object error like this:

const pluginLimitTitle = {
            beforeDraw: (chart) => {
                console.log(chart.scales.x.ticks);
                chart.scales.x.ticks = chart.scales.x.ticks.map(function (tick) {
                                var characterLimit = 12;
                                if (tick['label'].length >= characterLimit) {
                                    return tick['label'].slice(0, tick['label'].length).substring(0, characterLimit - 1).trim() + '...';
                                    ;
                                }
                                return tick;
                });
            }

I also tried putting the ticks callback inside the options on the chart creation on options: scales: x: ticks but it did not work either way.

Can someone help me make this on v3.x? Spent the whole day trying many things and don't look I'm getting closer to make it work.

After wasting many hours I found a "Tip" highlight on the documentation that should be in the examples, and not just badly highlighted on the "Labeling Axes" page.

When you do a callback for ticks on the chart options settings, you get 3 params to call:

function(value, index, ticks)

I tried in many ways to change the last one because it is the array of all ticks with their labels, and it is the only one where the label string appears so I was trying to modify it.

You'd think at first that the "value" parameter is the one to be changed, but it returns the exactly same integer value as the "index" parameter on each callback iteration, so I thought the only one the I could manipulate to change the string was the "ticks" array, but I was completely wrong.

You actually need to call a special function called getLabelForValue() .

The working code ended up like this:

const configTotal = {
    type: 'bar',
    data: dataTotal,
    options: {
        scales: {
            y: {
                beginAtZero: true
            },
            x: {
                ticks: {
                    callback: function(value, index, ticks_array) {
                        let characterLimit = 12;
                        let label = this.getLabelForValue(value);
                        if ( label.length >= characterLimit) {
                            return label.slice(0, label.length).substring(0, characterLimit -1).trim() + '...';
                        }
                        return label;
                    }
                }
            }
        }
    },
};

I hope this helps anyone having the same problem as me.

Maybe all the time I wasted is all on me for not reading every single line with more patience, but in my opinion, this documentation lacks a lot more example codes for accessing properties and callback parameters and it's object values, the way it is just showing the type of object and returns of each class method call, makes it very confusing for non-experienced on chart.js users.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM