chartjs / Chart.js

Simple HTML5 Charts using the <canvas> tag
https://www.chartjs.org/
MIT License
64.56k stars 11.9k forks source link

Graphical tick labels? #1554

Open SteveVanHorn opened 8 years ago

SteveVanHorn commented 8 years ago

Is there any way to use an image as a tick label in v2.0?

etimberg commented 8 years ago

This is currently not possible. I would be happy to merge a PR adding this, however.

benlower commented 8 years ago

I'd also like this feature. @etimberg do you happen to know where one would start to add this?

SteveVanHorn commented 8 years ago

I added a very hacky solution to accomplish what I needed. If I ever get the time, I plan on trying to implement something real and contribute it.

What I did was add an optional callback where the bar chart calls fillText to draw its label. The most obvious problem with it is that your graphic isn't taken into account when determining label dimensions so it better fit in the space that would have been taken up by the text label.

if (this.options.ticks.drawCallback) { this.options.ticks.drawCallback(this.ctx, label); } else { this.ctx.fillText(label, 0, 0); }

etimberg commented 8 years ago

@SteveVanHorn's solution seems like a good start. It should overload the fit function to ensure that the scale height / width is appropriately measured. https://github.com/chartjs/Chart.js/blob/master/src/core/core.scale.js#L253

joebeaver89 commented 7 years ago

@SteveVanHorn where did you add the code you referenced? I'd like to get this working (even in a hacky way!)

Cheers

etimberg commented 7 years ago

@joebeaver89 currently the text drawing happens here. It's been refactored a few times since the comment above but I think you'd need to replace that block with something that did custom drawing. Certainly the draw method is the place to look to implement this.

SteveVanHorn commented 7 years ago

Hey @joebeaver89, sorry this took so long. I just saw this.

If you look at the code that Evert linked to, I added my code right where it calls context.fillText(label, 0, 0); near the bottom of the highlighted area. Like he says, it has changed a little since I did mine but it is basically the same. Then you just need to pass in a callback function that can use context.drawImage() to draw your image. Just make sure the image is small enough to fit.

esradral commented 7 years ago

Would it be possible to give me an idiots guide on how to do this please? I'm creating childrens smiley face reward charts dynamically from mysql. I've got my chart working and generating an image which I can then incorporate into a pdf for download - all on the fly. The icing on the cake would be to have smiley face images on the yaxis ticks.

Any help or advice would be very much appreciated as I've tried following the comments above but I'm afraid my expertise is very limited when it comes to this depth of understanding code. Thanks in advance :-)

afaik-peace commented 6 years ago

a workaround

see fiddle , note the styling for this works at min 620px, https://jsfiddle.net/afaik_seeker/28fqbpes/

this is the image used in the fiddle above https://s9.postimg.cc/6yy3nc5hb/charts_js_fiddle_labels.png

alexeigs commented 4 years ago

@etimberg Has this ever been implemented? Is there by now a way to use material icons in the x-axis tick-callback (to e.g. replace "Today" by a calendar icon)?

etimberg commented 4 years ago

@alexeigs unfortunately this has not yet been implemented. To do it now in the code from the master branch one would need to override drawLabels in the Scale class https://github.com/chartjs/Chart.js/blob/master/src/core/core.scale.js#L1389

kurkle commented 4 years ago

You can use icon fonts (material, awesome etc): Example

alexeigs commented 4 years ago

@kurkle Does this also work for xAxes ticks (through the callback function)? I couldn't make that work so far...

kurkle commented 4 years ago

@alexeigs using the callback to generate the labels works just the same: https://codepen.io/kurkle/pen/OJMoagv?editors=1010

andredaa commented 3 years ago

@alexeigs using the callback to generate the labels works just the same: https://codepen.io/kurkle/pen/OJMoagv?editors=1010

I cannot get this to run inside vue.js It always shows me a text with the icon-name , but does not use the font. Any suggestion on what I might be doing wrong?

LeeLenaleee commented 3 years ago

@andredaa I gave it a quick try and got it to work in a Vue example: https://codepen.io/leelenaleee/pen/VwjgNGw?editors=0111

Data is not good but this was an old mr pen that I reused so it only shows labels for the first two items, didnt bother to fix it any more but I hope it can help you in why it didnt work for you

With some editing you can take @kurkle first example and instead of do it in the callbacks pass the things you want directly in the labels array (https://codepen.io/leelenaleee/pen/WNxzdVZ?editors=1010 not perfect but close to his example)

andredaa commented 3 years ago

@LeeLenaleee perfect! Thank you so much!

marcusparsons commented 1 year ago

I was able to get labels by utilizing the onComplete in the animation property. You could adjust this to do whatever you could do with a canvas such as displaying an image at that location.

animation: {
                duration: 800,
                onComplete: function () {
                    const ctx = this.ctx;
                    ctx.font = '11px Arial';
                    ctx.textAlign = 'center';
                    ctx.textBaseline = 'bottom';
                    ctx.fillStyle = 'white';

                    this.data.datasets.forEach(() => {
                        const chart = arguments[0].chart;

                        chart._sortedMetasets.forEach(metaset => {
                            metaset.data.forEach(bar => {
                                ctx.fillText(globalfn.nwc(bar.$context.raw), bar.x, bar.y - 5);
                            });
                        });
                    });
                }
            },