youcef92 / flotr

Automatically exported from code.google.com/p/flotr
0 stars 0 forks source link

Enhancement: Mouseover based on X-value #90

Open GoogleCodeExporter opened 8 years ago

GoogleCodeExporter commented 8 years ago
If there is only one series drawn in a line chart, it would be nice if
hovering the mouse near the X-value of a data-point would trigger the
mouseover/tooltip to be shown (regardless of the mouse pointers y-value). 

This feature would not neccessarily have much meaning for multiple lines on
the same chart though. 

Original issue reported on code.google.com by boem...@gmail.com on 14 Sep 2009 at 6:45

GoogleCodeExporter commented 8 years ago
Hmmm, you beat me to it... :)

Though I think it has a lot of meaning for multiple lines too (this is what I 
would
need). When using this feature, system could draw a vertical line instead of a 
circle
(this is a kind of standard) and display normal or customized (trackFormatter) 
message.

Judging from the sources the modification shouldn't be too difficult, but it 
would
require quite a lot of code change in hit() - I'm not sure I wish to dive in it 
just
yet. :)

Original comment by anz...@gmail.com on 17 Sep 2009 at 12:25

GoogleCodeExporter commented 8 years ago
Here is the fix that adds this feature. I hope it gets incorporated (or at least
another solution is added). 
With this fix, you can set options.mouse.trackAll to true - and that is all. The
color of the vertical line is taken from s.mouse.lineColor, the line width is 
taken
from s.points.lineWidth. The trackFormatter needs to be changed a bit (it must 
take
data from series_all instead of series).

It probably doesn't work with bars - don't need that, so.. ;) 
Not sure how it should look like with bars either.

Changes:
-----
1) in drawHit() change the line at the start:
    if(s.mouse.lineColor != null){
becomes:
    if (s.mouse.trackAll==true)
    {
            octx.save();i=1;
            octx.lineWidth = s.points.lineWidth;
            octx.strokeStyle = s.mouse.lineColor;
                octx.translate(this.plotOffset.left, this.plotOffset.top);
                octx.beginPath();
                octx.moveTo(xa.d2p(n.x), ya.d2p(0));
                octx.lineTo(xa.d2p(n.x), ya.d2p(n.yaxis.max));
                octx.stroke();
                octx.closePath();
            octx.restore();
    }
    else if(s.mouse.lineColor != null){
-----

2) in clearHit(), the line:
    if(!s.bars.show){
becomes:
    if (s.mouse.trackAll==true)
    {
    var bw = 1.0;
        lw=1.0;
    this.octx.clearRect(
      xa.d2p(prevHit.x - bw/2) + plotOffset.left - lw,
      ya.d2p(prevHit.yaxis.max) + plotOffset.top - lw,
      xa.d2p(bw) + lw * 2,
      ya.d2p(0) + lw * 2
        );
    }
    else if(!s.bars.show){
-----
3) in hit(), this line must be in 'else':
      for(i = 0; i < series.length; i++){
of this:
    if (options.mouse.trackAll==true)
    {
    s = series[0];
    data = s.data;
    xa = s.xaxis;
    ya = s.yaxis;
    xsens = (2*options.points.lineWidth)/xa.scale * s.mouse.sensibility;
    mx = xa.p2d(mouse.relX);
    my = ya.p2d(mouse.relY);

    for(var j = 0; j < data.length; j++){
        x = data[j][0];
        y = data[j][1];

          // not sure we need this, just copied it from below:
        if (y === null ||
            xa.min > x || xa.max < x ||
            ya.min > y || ya.max < y) continue;

        // make sure mx and my are on plot area:
        if (mx < xa.min || mx > xa.max ||
            my < ya.min || my > ya.max) continue;

        var xdiff = Math.abs(x - mx);

        // bars are not supported (yet?). Not sure how it should look with bars since
i don't use them.'
        if(((!s.bars.show) && xdiff < xsens)
//                ||(s.bars.show && xdiff < s.bars.barWidth/2 && ((y > 0 && my > 0 && my 
< y)
|| (y < 0 && my < 0 && my > y))) 
          )
        {
        var distance = xdiff;
        if(distance < n.dist){
            n.dist = distance;
            n.x = x;
            n.y = y;
            n.xaxis = xa;
            n.yaxis = ya;
            n.mouse = s.mouse;
            n.series = s; 
            n.series_all = series; // include all series, not just one!
            n.index = j;
        }
        }
      }
    }
    else {
      // here comes the previous for loop:
      for(i = 0; i < series.length; i++){
        // ...
      }
    }

-----
4) after this line in hit():
              n.series = s;
add this:
              n.series_all = series;
(so you remember all series data too - we need it for displaying the data in
trackFormatter)
-----
5) Change this line:
  mt.innerHTML = n.mouse.trackFormatter({x: n.x.toFixed(decimals), y:
n.y.toFixed(decimals), series: n.series, index: n.index, dataIndex: 
n.dataIndex}); 
to:
  mt.innerHTML = n.mouse.trackFormatter({x: n.x.toFixed(decimals), y:
n.y.toFixed(decimals), series: n.series, series_all: n.series_all, index: 
n.index,
dataIndex: n.dataIndex}); 
-----

This is it. To recapture the changes:
In hit():
- series_all is passed to trackFormatter (all series' data)
- hit becomes when x matches, y must only be on the plot area (when trackAll == 
true)

In drawHit():
- draw the line instead of circle (when trackAll == true)

In clearHit():
- invalidate different area (when trackAll == true)

Enjoy!

Original comment by anz...@gmail.com on 4 Jan 2010 at 3:04

GoogleCodeExporter commented 8 years ago
I have fixed it so it works with bars too. 

In step 3 just replace this line:
//                ||(s.bars.show && xdiff < s.bars.barWidth/2 && ((y > 0 && my > 0 && my 
< y)
|| (y < 0 && my < 0 && my > y))) // trackAll doesn't work with bars

with this one:
                  ||(s.bars.show && xdiff < s.bars.barWidth/2) 

Enjoy!

Original comment by anz...@gmail.com on 21 Apr 2010 at 1:14

GoogleCodeExporter commented 8 years ago
Fabien (& others), is there any chance you could add this functionality to 
trunk?

Original comment by anz...@gmail.com on 9 Aug 2010 at 11:56

GoogleCodeExporter commented 8 years ago

Original comment by fabien.menager on 12 Aug 2010 at 12:59

GoogleCodeExporter commented 8 years ago
As i have seen Carl has introduced some changes for bar charts. I will make 
some investigation about making it possible for other charts where it is 
reasonable

Original comment by macku30@gmail.com on 25 May 2011 at 6:44