简体   繁体   中英

d3JS: Bisecting a Nested Array

As a follow up to this question , I've managed to create a multi-series line chart out of nested arrays. I'm now trying to add tooltips to chart similar to the one on this post by Mike Bostock.

This means that I have to figure out a method for bisecting the nested array and then selecting those values for a tooltip. How do I transfer the lines of code below to a nested array?

bisectDate = d3.bisector(function(d) { return d.date; }).left,

Further into the script:

i = bisectDate(data, x0, 1),
    d0 = data[i - 1],
    d1 = data[i],

Thanks for any help, here is an example JS Fiddle which I'd like to use to create tooltips: http://jsfiddle.net/JYS8n/2/

You need to use bisect twice here, first to find the matching x value and then to find the matching y value. First, you'll need to define a second custom bisector that takes the value into account.

var bisectValue = d3.bisector(function(d) { return d.Value; }).left;

The first part of the handler is not changed a lot from the non-nested version. The only difference is that instead of considering only a single data series, we are iterating over all of them and collecting the closest data point for each.

var x0 = x.invert(d3.mouse(this)[0]),
    ds = data.map(function(e) {
        var i = bisectDate(e.Data, x0, 1),
            d0 = e.Data[i - 1],
            d1 = e.Data[i];
        return x0 - d0.Date > d1.Date - x0 ? d1 : d0;
    });

Now ds is a list of data points, the closest one to the cursor position for each series. All that remains to be done now is to bisect again to find the one with the closest value to the current cursor position.

var y0 = y.invert(d3.mouse(this)[1]),
    i = bisectValue(ds.sort(), y0, 1),
    d0 = ds[i - 1],
    d1 = ds[i],
    d = y0 - d0.Value > d1.Value - y0 ? d1 : d0;

The basic skeleton is the same as before, only this time we are comparing y and .Value . Now d is the data point to be highlighted.

focus.attr("transform", "translate(" + x(d.Date) + "," + y(d.Value) + ")");
focus.select("text").text(d.Value);

Full example here . I've also changed the line interpolation -- while that makes it look nicer, the line doesn't go through the actual points anymore.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM