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.
Answer
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.