Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Get point index from chart.getPointsAtEvent(e) #1283

Closed
maximilianschmitt opened this issue Jul 6, 2015 · 9 comments
Closed

Get point index from chart.getPointsAtEvent(e) #1283

maximilianschmitt opened this issue Jul 6, 2015 · 9 comments

Comments

@maximilianschmitt
Copy link

Hi, I am looking to make my chart a little more interactive and I would like to get a point's index (of its dataset) with the following code:

canvas.onclick = function(e) {
  const points = chart.getPointsAtEvent(e);
  // something like `point.getIndex()` would be great so that I know where this point is in the original dataset
};

Anybody have a good solution for this?

@maximilianschmitt
Copy link
Author

I am currently solving this by looking up the index of the label but it is a bit hacky...

@tyrex1975
Copy link

We're trying to resolve this too, was thinking of comparing the mouse position to the X/Y co-ords of each dataset, however scaling seems to be an issue.

@tyrex1975
Copy link

Whoops I slightly misread the original question. Our problem was when there are multiple datasets within a bar chart, when you use myBarChart.getBarsAtEvent(e) in the mouse click event, unfortunately you get an array of all of the datasets underneath the pointer, not the specific bar you clicked.

I hope you don't mind me posting our solution, because it might give you a clue as to how you can resolve the getPointsAtEvent issue as well :)

canvas.onclick = function(e) {
  var activePoints = myBarChart.getBarsAtEvent(e), // returns array of bars underneath pointer
      mouse_position = chart.helpers.getRelativePosition(e), // tells us the x/y of the mouse relative to the chart

  // Now filter the array to return just a single bar chart by computing the rectangle of the bar and checking whether the mouse pointer is inside it
  activePoints = $.grep(activePoints, function(activePoint, index) {
    var halfWidth = activePoint.width / 2, 
      leftX = activePoint.x - halfWidth, 
      rightX = activePoint.x + halfWidth, 
      top = activePoint.base - (activePoint.base - activePoint.y), 
      halfStroke = activePoint.strokeWidth / 2; 

    if (activePoint.showStroke) { 
      leftX += halfStroke; 
      rightX -= halfStroke; 
      top += halfStroke; 
    }

    return mouse_position.x >= leftX && mouse_position.x <=rightX && mouse_position.y >= top && mouse_position.y <= activePoint.base;
  });

  // activePoints[0] now contains just the bar you clicked!
};

@tyrex1975
Copy link

A small update - we've now carried out the above exercise for line charts too. We've assumed that each point is just a small rectangle, 10 x 10 pixels, and are detecting where the mouse pointer lies within those boundaries.

Just substitute the $.grep statement from the code above as follows:

activePoints = $.grep(activePoints, function(activePoint, index) {
  var leftX = activePoint.x - 5, 
    rightX = activePoint.x + 5, 
    topY = activePoint.y + 5, 
    bottomY = activePoint.y - 5; 

  return mouse_position.x >= leftX && mouse_position.x <=rightX && mouse_position.y >= bottomY && mouse_position.y <= topY;
});

@tneil
Copy link

tneil commented Aug 27, 2015

Thanks @tyrex1975 that was very helpful.. It would be great if in the future the activePoints came back with a selected boolean property so that we knew which ones were actually clicked at the point. Your work around worked great for me. Cheers!

@etimberg etimberg added the v1.x label Dec 25, 2015
@etimberg
Copy link
Member

Good solution from @tyrex1975
In v2, items have _index and _datasetIndex properties that can be used for better filtering. Alternatively using getElementAtPoint gets the first element at the point rather than all of them.

@maneljg
Copy link

maneljg commented Jul 15, 2016

Hello guys!

i would like , if its possible current dataset selected, if you click on label, or bar graph, but it doesn't have value, in my case, i just want to click label, or region and know the axisX value. Is it posible???
im trying your code, but it doesnt works with 0 value on axisY, just when i have value.
My case is i want to click in no values axisX, to show a popup, and the user, can set the value.

Any suggestions?

@sohampshetty
Copy link

sohampshetty commented Mar 2, 2017

@tyrex1975 It's not working for me, an error Uncaught TypeError: Cannot read property 'currentDevicePixelRatio' of undefined not leaving me alone.

var activePoints = lineChart.getElementsAtEvent(evt);
var mouse_position = Chart.helpers.getRelativePosition(evt); 

activePoints = $.grep(activePoints, function(activePoint, index) {
	var leftX = activePoint.x - 5,
		rightX = activePoint.x + 5,
		topY = activePoint.y + 5,
		bottomY = activePoint.y - 5;

	return mouse_position.x >= leftX && mouse_position.x <=rightX && 
                        mouse_position.y >= bottomY && mouse_position.y <= topY;
});

console.log(activePoints[0]);
console.log('activePoints[0]----');

@imdo
Copy link

imdo commented Apr 7, 2018

I made a workaround to get data from the clicked point;
As we know, the hover event fires before the event click, so I suggest the following solution

// declare a global variable
var selectedPoint;
// add the code below to your chartjs options
options: {
    .....,
    tooltips: {
        mode: 'single',
        callbacks: {
            afterBody: (data) => {
                if(data && data[0])
                selectedPoint = data[0];
                return [''];
            }
        }
}
// here you can use the global variable
canvas.onclick = function(e) {
   if(selectedPoint){
         // retrieve the data directly from selected point
         console.log("xLabel : "+selectedPoint.xLabel +" ,yLabel : "+selectedPoint.yLabel);
         // you can also retrieve the data && datasets
        console.log("datasets",myChart.config.data.datasets[selectedPoint.datasetIndex]);
console.log("data",myChart.config.data.datasets[selectedPoint.datasetIndex].data[selectedPoint.index]);
   }
};

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants