Chart.js get the nearest point when clicked on canvas
Asked Answered
E

3

7

is there a way to get the nearest point when clicked anywhere on canvas? Maybe somehow harvest the core 'nearest' method? Thanks

Electrostriction answered 31/5, 2019 at 3:48 Comment(2)
Welcome to Stack Overflow! Please take the tour, look around, and read through the Help Center, in particular How do I ask a good question? If you run into a specific problem, research it thoroughly, search thoroughly here, and if you're still stuck post your code and a description of the problem. Also, remember to include Minimum, Complete, Verifiable Example. People will be glad to helpNeon
@Neon Non-sense. This is a clear question.Mabe
E
5

I think you will find getElementsAtXAxis very helpful.

Basically, getElementsAtXAxis has a very similar behaviour to getElementsAtEvent although when the click event doesn't intersect a point of the chart, it will return the nearest ChartElement.

The only downside is that it will return all the ChartElement on the nearest x-axis index.

So, if you use multiple datasets, this might not be the best choice for you.

Code example:

canvas.onclick = function(e) {
    const elts = chart.getElementsAtXAxis(simulatedEvent);
    if (elts && elts.length) {
        // Do something with elts[0]
    }
};

If anyone is looking for the related piece of code, it's in core.controller.js:

getElementAtEvent: function(e) {
    return Interaction.modes.nearest(this, e, {intersect: true});
},

getElementsAtEvent: function(e) {
    return Interaction.modes.index(this, e, {intersect: true});
},

getElementsAtXAxis: function(e) {
    return Interaction.modes.index(this, e, {intersect: false});
},
Elyseelysee answered 22/5, 2020 at 19:33 Comment(0)
C
0

I believe you are looking for .getElementAtEvent and .getElementsAtEvent (https://www.chartjs.org/docs/latest/developers/api.html#getelementsatevente)

What you can do - is set up a clickHandler function that will grab the event from onClick and use it to return the chart element under it.

Here is an example from the official docs:

function clickHandler(evt) {
    var firstPoint = myChart.getElementAtEvent(evt)[0];

    if (firstPoint) {
        var label = myChart.data.labels[firstPoint._index];
        var value = myChart.data.datasets[firstPoint._datasetIndex].data[firstPoint._index];
    }
}

After, just add it to your chart canvas (again, from the official docs):

canvas.onclick = clickHandler;
Caerleon answered 31/5, 2019 at 6:29 Comment(3)
While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. - From ReviewPetta
@Mayur, thank you for the suggestion. I edited the answer to pull the essential parts of the docs into it.Caerleon
Hey, thanks for the answer. .getElementAtEvent and .getElementsAtEvent only return elements at the position where you clicked. When I click just randomly on the canvas, it returns an empty array. I would need to get the nearest element wherever I click, hence the mentioned 'nearest' method in the core link . This question has been already asked numerous times before with (for me) incorrect answers and no followups, such as: linkElectrostriction
F
0

I achieved this in a graph with two datasets with the following:

const userPricingEl = document.getElementById("userPricingChart");
const userPricingChart = new Chart();

userPricingEl.onclick = function (evt) {
    let nearestPoints = userPricingChart.getElementsAtEventForMode(evt, "nearest", {
        intersect: false
    });
    if (nearestPoints) {
        let nearestPoint = nearestPoints[0];
        let label = userPricingChart.data.datasets[nearestPoint._datasetIndex].label;
        let value = userPricingChart.data.datasets[nearestPoint._datasetIndex].data[nearestPoint._index];
        console.log(label, value);
    }
}

Where "userPricingChart" is a fully fleshed out new Chart() object, which I omitted for brevity.

The key feature here is the getElementsAtEventForMode() function, documented here (albeit arguably badly).

Hope this helps.

Fallfish answered 21/1, 2023 at 1:8 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.