1

following up the creation of a chart from another question I had raised, and by studying this thread that contains information on how to bisect a nested array, I enriched my chart to zoom-able and resposnive.

I am so close to completing it, just a few things missing that I thought would be a lot easier. I am currently stuck at the tooltips. The desired effect is for a tooltip to appear when hovering over the chart and show current date, line names and line values. I tried a lot of things, but can't get the expected result.

Moreover, I am not sure about the bisection. Am I doing it right? The original dataset is turned to a nested array and then for bisection it is manipulated again. Is this the right way to do it or would it be safe to use the original dataset?

I am looking for fail-safe to create tooltips that would work in other cases as well - not just this specific chart, so any advice and/or suggestions are more than welcome.

My code for the tooltip is as follows:

var mousemoveFunc = function(d, i) {
      var d, d0, d1, i, x0, left, mouse, top;
      x0 = xz.invert(d3.mouse(this)[0]);
      ds = dataGroup.map(function(e) {
        var i = bisectDate(e.values, x0, 1),
            d0 = e.values[i - 1],
            d1 = e.values[i];
        return d = x0 - d0.date > d1.date - x0 ? d1 : d0;
        }); 

      mouse = d3.mouse(svg.node()).map(function(d) {
        return parseInt(d);
      });

      left = Math.min(containerwidth, mouse[0]+margin.left+margin.right);
      top = Math.min(containerheight, mouse[1]+margin.top+margin.right);

      tooltip.data(ds).classed('hidden', false).attr('style', 'left:' + left + 'px;top:' + top + 'px;margin-top:' + (-margin.top) + 'px;').html(function(d,i) { 

        for (var i = 0; i < ds.length; i++){
            if (ds[i].date === d.date){
              return ds[i].name + ' ' + ds[i].value;
            }
          }
      });
    };

..I am almost certain that it is wrong to reattach data(ds) on the tooltip, but it was the only way I could manage to show results.

I have created the following fiddle: https://jsfiddle.net/2en21Lqh/4/

:/ Now that I am currently writing the post, I just realised that attaching data on a single element is totally wrong, since the function(d) would only run once.

Community
  • 1
  • 1
scooterlord
  • 15,124
  • 11
  • 49
  • 68
  • You have some interesting options here. First, you could show the tooltip when you hover near the point. Or, you could show the "closest" tooltip using a [voronoi tooltip](http://bl.ocks.org/nbremer/65f03d1ebd1742196200). Or, you could do a "continuous tooltip" like [this](http://stackoverflow.com/a/34887578/16363). I'll answer below for the simplest approach. – Mark Mar 23 '17 at 15:42
  • @Mark, actually what I am looking for is to have the results in the tooltip I am already showing - that is the tooltip should follow the mouse cursor and show the results there. edit: to make it clearer: show vallues for ALL lines at the same time inside the same tooltip. – scooterlord Mar 23 '17 at 15:43
  • I understand, just wanted to point out the options you have... – Mark Mar 23 '17 at 15:46
  • @Mark thanks! Actually the next step would also be to add a vertical line and showing points as in your second example, however, from a few things I tried it is messed up by the zoom functionality. If it is something easy to be implemented though, please help a drowning man! – scooterlord Mar 23 '17 at 15:47

1 Answers1

1

Here's my implementation of your mousemove function:

var mousemoveFunc = function(d, i) {

  var x0 = xz.invert(d3.mouse(this)[0]);

  var lastDate,
      ds = dataGroup.map(function(e) { 
        var i = bisectDate(e.values, x0, 1),
            d0 = e.values[i - 1],
            d1 = e.values[i];

        var d = x0 - d0.date > d1.date - x0 ? d1 : d0;

        lastDate = d.date;
        return e.key + " " + d.value;
      });

  var left = d3.event.x,
      top = d3.event.y;      

  tooltip
    .html(lastDate.toString() + "<br/>" + ds.join("<br/>"))
    .classed('hidden', false)
    .style('left', left + 'px')
    .style('top', top + 'px');

};

Updated fiddle.

Mark
  • 106,305
  • 20
  • 172
  • 230
  • In the meantime I came up with a different solution, but I'll see what I can learn from your code as well. How easy would it be to implement the line and focus points from your other answer? http://stackoverflow.com/questions/34886070/multiseries-line-chart-with-mouseover-tooltip/34887578#34887578 – scooterlord Mar 23 '17 at 16:02
  • @scooterlord, added your line. Click fiddle link above. – Mark Mar 23 '17 at 16:02
  • @scooterlord, so that's a different beast. You want to show "continuous tooltip"; meaning that you extrapolate values from the line, but those values don't actually exist in your data? – Mark Mar 23 '17 at 16:03
  • The required result is the tooltip to follow the cursor but also have a vertical line with circle marks that show the corresponding data. – scooterlord Mar 23 '17 at 16:05
  • ...so the vertical line should 'snap' to the x axis values rather than following the lines - i guess it is much easier than the continuous line. – scooterlord Mar 23 '17 at 16:07
  • Well yes, exactly like this. You spent something like 2 mins for what would probably take me hours to implement. However, it breaks on zoom. Is there any easy way to make this work on all zoom levels? - Also, thanks for all your support. I am paying it forward to others, just so you know :) – scooterlord Mar 23 '17 at 16:11
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/138853/discussion-between-mark-and-scooterlord). – Mark Mar 23 '17 at 16:14
  • hopefully you are still around. I updated my fiddle to add focuspoints here https://jsfiddle.net/2en21Lqh/10/ . I am now trying to move the focuspoint in the y axis when hovered on - I am so close, but can't get to it. Console log gives me the right values, but the map objects are returned in the cy attribute. I also have a question: since the focuspoints are appended inside linesEnter they are already bound to the fData, right? If I got this right, very soon I'll increase level! – scooterlord Mar 24 '17 at 11:01
  • Also, I just noticed update v9 you had posted that also includes circles. However, everything breaks on zoom / windows resize :/ – scooterlord Mar 24 '17 at 11:48