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

Show tooltips based on cursors x position in line charts #2299

Closed
ghost opened this issue Apr 19, 2016 · 31 comments
Closed

Show tooltips based on cursors x position in line charts #2299

ghost opened this issue Apr 19, 2016 · 31 comments

Comments

@ghost
Copy link

ghost commented Apr 19, 2016

Hi,

I'm working with scatter charts and a large amount of points which results in an overlapping of the hover areas while trying to trigger the tooltips. I would like to bypass this mechanism and use the current x position of the mouse cursor instead to show the corresponding tooltip on the line chart. Here is an example of what I'm trying to describe in flotcharts:
http://www.flotcharts.org/flot/examples/tracking/index.html

It looks like this was the normal behavior of line charts in v1 to trigger the tooltips, but is it still possible to do this with v2?

@lone-cloud
Copy link

Facing the same challenge...I'd love to know how to approach implementing this too.

@lone-cloud
Copy link

I highly doubt the core devs will respond as their rules clearly state that we should not be asking support questions in the issue tracker ( use stackoverflow with the appropriate tag ).
I ended up implementing something similar that you can see here: http://hoboman313.github.io/chartsjs-demo/
Note that I created this solely as a demo to show off to some designers, so the code is pretty shit. I couldn't figure out how to properly extend the Chart.elements.Point:inRange() properly to be used by the Chart.line so I ended up monkey patching the library >_<.

@etimberg
Copy link
Member

@mdh-cc @hoboman313 I think you need to use the inLabelRange function of the point elements.

What you could do is replace the getElementAtEvent and getElementsAtEvent functions with versions that use inLabelRange instead of inRange. You should be able to do this after charts are created.

I'd be happy to merge a PR adding a new tooltip mode that added this functionality. I can give you some direction in implementing it if necessary

@ericcirone
Copy link

@etimberg I would love to see how to implement this also for a Line chart. Any example code would be great. Thanks!

@etimberg
Copy link
Member

@ericcirone I created a fiddle for you. In it I hotpatch the getElementsAtEvent method on the main chart controller to use inLabelRange.

https://jsfiddle.net/a077grhm/

@ericcirone
Copy link

@etimberg Thanks so much! Hopefully this is can be implemented as a new tooltip mode. Side note, on a bar chart, when you are on top of the bar the bar goes into hover mode, but doesn't display the tooltip. Any idea?

@etimberg
Copy link
Member

@ericcirone It'd make a great mode. To anyone who comes across this, I'd be happy to accept a PR for this.

is the tooltip mode set to label?

config = {
  tooltip: {
    mode: 'label'
  }
}

@ericcirone
Copy link

@etimberg You got it. I forgot to set those to label. Thanks a bunch.

@ghost
Copy link
Author

ghost commented Apr 29, 2016

@etimberg Thank you for the fiddle, this should solve my current problem.

@ThaJay
Copy link

ThaJay commented May 17, 2016

isDatasetVisible does not seem to be a part of helpers at this time in 2.1.3. I noticed you're using 2.0.2 in the fiddle @etimberg.
I found this.isDatasetVisible to be valid but now its dataset is undefined. Could you point me in the right direction? or should I SO this question?

It would be great if this functionality can become a standard option again (it was in 1.x)

@etimberg
Copy link
Member

@ThaJay here's an updated version of the fiddle: https://jsfiddle.net/a077grhm/3/

This is on our radar to add back. If someone wants to PR it I'd happily merge it. They'd need a new mode string to set the tooltip to this mode, and a new function to that does what the fiddle does. I'd be happy to discuss refactoring this. I think that these functions should be stored somewhere else so they're easier to patch and extend

@ThaJay
Copy link

ThaJay commented May 17, 2016

Nice thanks!
It would have taken me days to figure out all those small api changes, but your fiddle works for us.
So far, you guys have impressed me with your fast and high quality responses on here, very good work.

@etimberg
Copy link
Member

Glad it works for your use case. I'll try and add this back before the next release so that you don't need any hacks to make it work 😃

@olyckne
Copy link
Contributor

olyckne commented May 18, 2016

I've built a plugin for this which we use on PriceSpy (https://m.pricespy.co.uk/product/3499390/statistics)
The difference is that we show a tooltip until we reach a new one (we have so many data points it will be a lot of "blinking" otherwise)

Would be nice to have in core.

If it might be of any help this is the function that's called on onclick, onmousemove and ontouchmove.
I guess it need some minor tuning to work with multiple datasets.

let activeTooltip = null;

function showTooltipForPointEvenIfNotHoveringExactlyOverIt(chartInstance, evt) {
  const helpers = Chart.helpers;
  const eventPosition = helpers.getRelativePosition(evt, chartInstance.chart);

  helpers.each(chartInstance.data.datasets, (dataset, datasetIndex) => {
    if (chartInstance.isDatasetVisible(datasetIndex)) {
      helpers.each(chartInstance.getDatasetMeta(datasetIndex).data, element => {
        if (element.inLabelRange(eventPosition.x, eventPosition.y)) {
          activeTooltip = element;
          return;
        }
      });
    }
  });

  if (activeTooltip) {
    chartInstance.tooltipActive.push(activeTooltip);
    chartInstance.tooltip.update(true);
    chartInstance.render(0, true);
  }
}

@ghost
Copy link

ghost commented Jun 27, 2016

@etimberg: This is exactly what I was looking for -- I'll give it a shot and report back.

Thanks!

@ghost
Copy link

ghost commented Jun 28, 2016

@etimberg: Just tried your hotfix with the 2.1.6 release, but it's giving me an error:
Uncaught TypeError: helpers.isDatasetVisible is not a function

Any idea what could be causing this?

EDIT: Actually, it looks like there are some changes between the Charts JS version used in the fiddle and the current release. I have an idea how to hack it together. I'll give it a shot and report back (again).

@etimberg
Copy link
Member

@adamtLICOR isDatasetVisible is now a method on the core chart instance.https://github.com/chartjs/Chart.js/blob/master/src/core/core.controller.js#L481

@ghost
Copy link

ghost commented Jun 28, 2016

Yup, I figured that part out. I tried copying the getElementsAtEvent() method and just swapping in inLabelRange, but that doesn't seem to do the trick (still only highlights on the literal dot).

Here's my new code, maybe I'm missing something:

    getElementsAtXAxis: function(e){
        var me = this;
        var eventPosition = helpers.getRelativePosition(e, me.chart);
        var elementsArray = [];

        var found = (function() {
            if (me.data.datasets) {
                for (var i = 0; i < me.data.datasets.length; i++) {
                    var meta = me.getDatasetMeta(i);
                    if (me.isDatasetVisible(i)) {
                        for (var j = 0; j < meta.data.length; j++) {
                            if (meta.data[j].inLabelRange(eventPosition.x, eventPosition.y)) {
                                return meta.data[j];
                            }
                        }
                    }
                }
            }
        }).call(me);

        if (!found) {
            return elementsArray;
        }

        helpers.each(me.data.datasets, function(dataset, datasetIndex) {
            if (me.isDatasetVisible(datasetIndex)) {
                var meta = me.getDatasetMeta(datasetIndex);
                elementsArray.push(meta.data[found._index]);
            }
        }, me);

        return elementsArray;
    }

@ghost
Copy link

ghost commented Jun 28, 2016

@etimberg -- Annnnd, I'm dumb -- I was setting the hover mode on the chart hover, but not on the tooltip. :)

It seems to work now, just fine.

If you're still looking for someone to PR the fix, I'd be more than happy to make one!

@etimberg
Copy link
Member

@adamtLICOR please feel free to PR this. I think we should add a new mode for this (since it is different than the current label model which some may want).

@Mesonyx
Copy link
Contributor

Mesonyx commented Jun 28, 2016

@etimberg: Okay, great! Working on it now!

(I'm the same dude -- @adamtLICOR -- just on my personal account, instead of my work account)

@Mesonyx
Copy link
Contributor

Mesonyx commented Jun 28, 2016

Thanks for all your help!

@lakjakmr
Copy link

lakjakmr commented Aug 10, 2016

Hi Friends,
I am trying to get that thick vertical line as cursor point to display this label as show in initial request
http://www.flotcharts.org/flot/examples/tracking/index.html

What should I add to Etimberg's method to make the line visible ? any help will be appreciated

@RoxKilly
Copy link

RoxKilly commented Aug 19, 2016

@lakjakmr from reading this board, I think you need to update to the latest version and set the tooltip mode in your configuration to 'label' or 'x-axis'

config = {
  tooltips: {
    mode: 'label'  // or 'x-axis'
  }
}

@jdudley1123
Copy link

The docs now say that x-axis mode is deprecated (change made by @etimberg), and suggests using index mode with intersect = false, but that doesn't seem to replicate this functionality.

Is this a bug, or was x-axis mode just marked deprecated by mistake?

@etimberg
Copy link
Member

@jdudley1123 the docs have an error. It should read intersect = true.

@jdudley1123
Copy link

jdudley1123 commented Dec 28, 2016

@etimberg Actually intersect = false is right, it was my error. Fiddle shows it working: https://jsfiddle.net/o30ne2w9/

Sorry to have bothered you!

@seltix5
Copy link

seltix5 commented Sep 21, 2017

hi,
sorry to post this question but, i was trying to set a vertical line folowing the mouse like @hoboman313 did in his example here http://hoboman313.github.io/chartsjs-demo/, is it possible?
Thanks.

@dimanado
Copy link

hi, sorry, but i can't find how do the same in 2.8.0 (https://jsfiddle.net/a077grhm/3/)

@ammreach
Copy link

@hoboman313 can you show me the code of your http://hoboman313.github.io/chartsjs-demo/, to be honest i am trying to build the same in ANGULAR, face lots of problems now.

@lone-cloud
Copy link

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

No branches or pull requests