BigBear.ai
  • Home
  • Industries
    • Academia
    • Government
    • Healthcare
    • Manufacturing
  • Solutions
    • Cyber
    • Data Analytics
    • Enterprise Planning and Logistics
    • Intelligent Automation
    • Modeling Solutions
    • Professional Services
  • Company
    • About
    • Investor Relations
    • Partners
    • Team
  • Careers
    • Benefits
    • Culture
    • Explore Jobs
    • Military and Veterans
    • Applicant Login
    • Employee Login
  • Resources
    • Blog
    • Events
    • Newsroom
    • Resource Library
    • Online Store
  • Contact
Search

Home Technology Plotly.js: Getting Accurate Coordinates from Click Event

Blog

Plotly.js: Getting Accurate Coordinates from Click Event

Samantha Hamilton
September 4, 2019

Across StackExchange and the Plotly.js community forums, there seems to be one frequently asked question that has not yet been answered: how can you get accurate coordinates from a click event on a Plotly chart?

Take your standard scatter plot: https://codepen.io/plotly/pen/LVMRMO

plotly figure
Figure 1

If I hover my mouse over (4, 14), and click, the current Plotly.js onClick event data returns data for each trace at that same x value. So, you would get (4, 17) for trace 0, (4, 11) for trace 1, and (4, 12) for trace 2. This is great if I’m trying to find out information about the traces, but this is not useful at all if I’m trying to get the point on the grid on which I clicked.

Of course, with the event data you get all kinds of other somewhat useful information and functions. etpinard gets close to a solution in this codepen (https://codepen.io/plotly/pen/EyydEj) by using the xaxis and yaxis built-in p2c function. Unfortunately, this doesn’t exactly work, and there is little to no documentation on these conversion functions. There are a few other efforts that take into account the margins of the chart div (https://codepen.io/plotly/pen/BgWLzP), but these also fall short of the mark when it comes to accuracy.

So, if you want the exact coordinates of where you clicked, what are your options? Go rogue D3 and write a custom function? Switch charting libraries completely out of frustration?

The answer, as is the answer to most of my questions with Plotly, is to layer traces. In a nutshell, layering a heatmap trace below all other traces on the plot, utilizing the same axes as the other traces, enables you to get the exact coordinates of a click. How exactly does this work?

By definition, a heatmap is a data visualization where every individual (x, y) pair is assigned a z value, and then colored according to that z-value. The basic Plotly.js heatmap can be seen here (https://codepen.io/plotly/pen/NqJzgm). The Plotly.js heatmap is a combination of three arrays: a 1-d x-axis array, a 1-d y-axis array, and a 2-d z array. Because this chart covers the entire x-y space of the plot, we can get the x-y coordinates for any click event. However, the exactness of those coordinates is based on the x-y intervals from the heatmap’s data.

Plotly figure
Figure 2

So, let’s make a heatmap with extremely granular x-y intervals: https://codepen.io/plotly/pen/VoGbyR. Looks pretty cool, huh? Let’s use something like this to get accurate click data for a scatter plot.

scatter plot
Figure 3

The first step is to generate the heatmap trace according to your data. If we are using Plotly’s out of the box scatter example, the x axis range is [0,6] and the y-axis range is [0,18]. Let’s plan for the x-y scale of the heatmap to be 0.01, so using two separate loops, we prime the x and y arrays for the heatmap:

var x = [];  
var y = [];  
for(i = 0; i < 6; i = i + 0.01){  
  x.push(i);  
}  
for(j = 0; j < 18; j = j + 0.01){  
  y.push(j);  
} 

Now that the x and y arrays are created, we can use these to generate an appropriately sized z array. Because we don’t actually care about the z value for this implementation, we will set each z array value to 0:

var z = [];  
for (j = 0; j < y.length; j++) {  
  var temp = [];  
  for (k = 0; k < x.length; k++) {  
    temp.push(0);  
  }  
  z.push(temp);  
} 

The final step is to configure the heatmap data trace using the three arrays we just created. A few notes: the colorscale is manually set so that a z-value of 0 shows as white, to prevent the trace from being visible behind the other traces. Setting the showscale value to false hides the colorbar in the legend, and setting the hoverinfo to ‘x’ prevents the heatmap from showing its values as you pan across the chart. The xgap and ygap values allow the axes grid lines to continue to show through the hidden heatmap layer. I’m sure there is more parameters that could be added to make this trace even more difficult to discern, but I’ll leave that for you to play around with.

var trace4 = {  
  x: x,  
  y: y,  
  z: z,  
  type: "heatmap",  
  colorscale: [["0.0", "rgb(255, 255, 255, 0.5)"], ["1.0", "rgb(255, 255, 255, 0.5)"]],  
  xgap: 1,  
  ygap: 1,  
  hoverinfo: "x",  
  showscale: false  
}

Now, adding this trace into the data array for the scatter plot doesn’t make it look much different than before:

Figure 4

The last thing that needs to be done is to actually bind to the click event and see the data. This can vary depending on your implementation (react-ploty, Angular, etc), so I’ll leave the implementation up to you. The click event data returns an array of points. Each object in this array has a curveNumber attribute; this number is the index of that data trace in the data array that was utilized to make the chart. Using an array filter function, you can grab the specific object that relates to the heatmap trace, then use the x and y attributes belonging to that object, and voila, you have the exact coordinates of your click.

The full solution is up and running in a rudimentary codepen here: https://codepen.io/plotly/pen/bXxWQB

This solution may add overhead to the chart render because it adds an extra trace to your chart. Also, if your chart has multiple axes scales, things could go sideways quickly. However, this is one sure-fire way to get the exact coordinates that you clicked upon, without some wonky point to coordinate conversions that return different values each time. Enjoy!

Posted in Technology.
BigBear.ai
  • Home
  • Industries
  • Solutions
  • Company
  • Careers
  • Blog
  • Investor Relations
  • Contact
  • Twitter
  • Facebook
  • Linkedin
  • Google My business for BigBear.ai
1-410-312-0885
[email protected]
  • Privacy Policy
  • Terms of Use
  • Accessibility
  • Site Map
© BigBear.ai 2023
We value your privacy
We use cookies on our website to give you the most relevant experience by remembering your preferences and repeat visits. By clicking “Accept”, you consent to the use of ALL the cookies.
Privacy Policy | Do not sell my personal information
AcceptCookie Settings
Manage Consent

Cookies Overview

This website uses cookies to improve your experience while you navigate through the website. Out of these, the cookies that are categorized as necessary are stored on your browser as they are essential for the working of basic functionalities of the website. We also use third-party cookies that help us analyze and understand how you use this website. These cookies will be stored in your browser only with your consent. You also have the option to opt-out of these cookies. But opting out of some of these cookies may affect your browsing experience.
Necessary
Always Enabled
Necessary cookies are absolutely essential for the website to function properly. These cookies ensure basic functionalities and security features of the website, anonymously.
CookieDurationDescription
cookielawinfo-checkbox-analytics11 monthsThis cookie is set by GDPR Cookie Consent plugin. The cookie is used to store the user consent for the cookies in the category "Analytics".
cookielawinfo-checkbox-functional11 monthsThe cookie is set by GDPR cookie consent to record the user consent for the cookies in the category "Functional".
cookielawinfo-checkbox-necessary11 monthsThis cookie is set by GDPR Cookie Consent plugin. The cookies is used to store the user consent for the cookies in the category "Necessary".
cookielawinfo-checkbox-others11 monthsThis cookie is set by GDPR Cookie Consent plugin. The cookie is used to store the user consent for the cookies in the category "Other.
cookielawinfo-checkbox-performance11 monthsThis cookie is set by GDPR Cookie Consent plugin. The cookie is used to store the user consent for the cookies in the category "Performance".
JSESSIONIDsessionThe JSESSIONID cookie is used by New Relic to store a session identifier so that New Relic can monitor session counts for an application.
viewed_cookie_policy11 monthsThe cookie is set by the GDPR Cookie Consent plugin and is used to store whether or not user has consented to the use of cookies. It does not store any personal data.
Functional
Functional cookies help to perform certain functionalities like sharing the content of the website on social media platforms, collect feedbacks, and other third-party features.
CookieDurationDescription
__atuvc1 year 1 monthAddThis sets this cookie to ensure that the updated count is seen when one shares a page and returns to it, before the share count cache is updated.
__atuvs30 minutesAddThis sets this cookie to ensure that the updated count is seen when one shares a page and returns to it, before the share count cache is updated.
Analytics
Analytical cookies are used to understand how visitors interact with the website. These cookies help provide information on metrics the number of visitors, bounce rate, traffic source, etc.
CookieDurationDescription
_ga2 yearsThe _ga cookie, installed by Google Analytics, calculates visitor, session and campaign data and also keeps track of site usage for the site's analytics report. The cookie stores information anonymously and assigns a randomly generated number to recognize unique visitors.
_ga_NK4L4Q320Q2 yearsThis cookie is installed by Google Analytics.
_gat_gtag_UA_163894009_21 minuteSet by Google to distinguish users.
_gid1 dayInstalled by Google Analytics, _gid cookie stores information on how visitors use a website, while also creating an analytics report of the website's performance. Some of the data that are collected include the number of visitors, their source, and the pages they visit anonymously.
at-randneverAddThis sets this cookie to track page visits, sources of traffic and share counts.
CONSENT2 yearsYouTube sets this cookie via embedded youtube-videos and registers anonymous statistical data.
uvc1 year 1 monthSet by addthis.com to determine the usage of addthis.com service.
Advertisement
Advertisement cookies are used to provide visitors with relevant ads and marketing campaigns. These cookies track visitors across websites and collect information to provide customized ads.
CookieDurationDescription
f5avraaaaaaaaaaaaaaaa_session_sessionbusinesswire.com cookie
loc1 year 1 monthAddThis sets this geolocation cookie to help understand the location of users who share the information.
VISITOR_INFO1_LIVE5 months 27 daysA cookie set by YouTube to measure bandwidth that determines whether the user gets the new or old player interface.
YSCsessionYSC cookie is set by Youtube and is used to track the views of embedded videos on Youtube pages.
yt-remote-connected-devicesneverYouTube sets this cookie to store the video preferences of the user using embedded YouTube video.
yt-remote-device-idneverYouTube sets this cookie to store the video preferences of the user using embedded YouTube video.
Save & Accept