javascript - Flot: How do I grab the nearest plotted point to where the cursor is? - Stack Overflow

I am trying to grab the nearest plotted point that the cursor is to. II found the findNearbyItem functi

I am trying to grab the nearest plotted point that the cursor is to. I

I found the findNearbyItem function in the jquery.flot.js source that seems to be able to do this, but when I trie calling it manually, I received the ReferenceError: findNearbyItem is not defined error.

This is the function I am referring to:

function findNearbyItem(mouseX, mouseY, seriesFilter) {
    var maxDistance = options.grid.mouseActiveRadius,
        smallestDistance = maxDistance * maxDistance + 1,
        item = null, foundPoint = false, i, j, ps;

    for (i = series.length - 1; i >= 0; --i) {
        if (!seriesFilter(series[i]))
            continue;

        var s = series[i],
            axisx = s.xaxis,
            axisy = s.yaxis,
            points = s.datapoints.points,
            mx = axisx.c2p(mouseX), // prepute some stuff to make the loop faster
            my = axisy.c2p(mouseY),
            maxx = maxDistance / axisx.scale,
            maxy = maxDistance / axisy.scale;

        ps = s.datapoints.pointsize;
        // with inverse transforms, we can't use the maxx/maxy
        // optimization, sadly
        if (axisx.options.inverseTransform)
            maxx = Number.MAX_VALUE;
        if (axisy.options.inverseTransform)
            maxy = Number.MAX_VALUE;

        if (s.lines.show || s.points.show) {
            for (j = 0; j < points.length; j += ps) {
                var x = points[j], y = points[j + 1];
                if (x == null)
                    continue;

                // For points and lines, the cursor must be within a
                // certain distance to the data point
                if (x - mx > maxx || x - mx < -maxx ||
                    y - my > maxy || y - my < -maxy)
                    continue;

                // We have to calculate distances in pixels, not in
                // data units, because the scales of the axes may be different
                var dx = Math.abs(axisx.p2c(x) - mouseX),
                    dy = Math.abs(axisy.p2c(y) - mouseY),
                    dist = dx * dx + dy * dy; // we save the sqrt

                // use <= to ensure last point takes precedence
                // (last generally means on top of)
                if (dist < smallestDistance) {
                    smallestDistance = dist;
                    item = [i, j / ps];
                }
            }
        }

        if (s.bars.show && !item) { // no other point can be nearby
            var barLeft = s.bars.align == "left" ? 0 : -s.bars.barWidth/2,
                barRight = barLeft + s.bars.barWidth;

            for (j = 0; j < points.length; j += ps) {
                var x = points[j], y = points[j + 1], b = points[j + 2];
                if (x == null)
                    continue;

                // for a bar graph, the cursor must be inside the bar
                if (series[i].bars.horizontal ?
                    (mx <= Math.max(b, x) && mx >= Math.min(b, x) &&
                     my >= y + barLeft && my <= y + barRight) :
                    (mx >= x + barLeft && mx <= x + barRight &&
                     my >= Math.min(b, y) && my <= Math.max(b, y)))
                        item = [i, j / ps];
            }
        }
    }

    if (item) {
        i = item[0];
        j = item[1];
        ps = series[i].datapoints.pointsize;

        return { datapoint: series[i].datapoints.points.slice(j * ps, (j + 1) * ps),
                 dataIndex: j,
                 series: series[i],
                 seriesIndex: i };
    }

    return null;
}

If there are alternate ways of solving this problem, please let me know.

I am trying to grab the nearest plotted point that the cursor is to. I

I found the findNearbyItem function in the jquery.flot.js source that seems to be able to do this, but when I trie calling it manually, I received the ReferenceError: findNearbyItem is not defined error.

This is the function I am referring to:

function findNearbyItem(mouseX, mouseY, seriesFilter) {
    var maxDistance = options.grid.mouseActiveRadius,
        smallestDistance = maxDistance * maxDistance + 1,
        item = null, foundPoint = false, i, j, ps;

    for (i = series.length - 1; i >= 0; --i) {
        if (!seriesFilter(series[i]))
            continue;

        var s = series[i],
            axisx = s.xaxis,
            axisy = s.yaxis,
            points = s.datapoints.points,
            mx = axisx.c2p(mouseX), // prepute some stuff to make the loop faster
            my = axisy.c2p(mouseY),
            maxx = maxDistance / axisx.scale,
            maxy = maxDistance / axisy.scale;

        ps = s.datapoints.pointsize;
        // with inverse transforms, we can't use the maxx/maxy
        // optimization, sadly
        if (axisx.options.inverseTransform)
            maxx = Number.MAX_VALUE;
        if (axisy.options.inverseTransform)
            maxy = Number.MAX_VALUE;

        if (s.lines.show || s.points.show) {
            for (j = 0; j < points.length; j += ps) {
                var x = points[j], y = points[j + 1];
                if (x == null)
                    continue;

                // For points and lines, the cursor must be within a
                // certain distance to the data point
                if (x - mx > maxx || x - mx < -maxx ||
                    y - my > maxy || y - my < -maxy)
                    continue;

                // We have to calculate distances in pixels, not in
                // data units, because the scales of the axes may be different
                var dx = Math.abs(axisx.p2c(x) - mouseX),
                    dy = Math.abs(axisy.p2c(y) - mouseY),
                    dist = dx * dx + dy * dy; // we save the sqrt

                // use <= to ensure last point takes precedence
                // (last generally means on top of)
                if (dist < smallestDistance) {
                    smallestDistance = dist;
                    item = [i, j / ps];
                }
            }
        }

        if (s.bars.show && !item) { // no other point can be nearby
            var barLeft = s.bars.align == "left" ? 0 : -s.bars.barWidth/2,
                barRight = barLeft + s.bars.barWidth;

            for (j = 0; j < points.length; j += ps) {
                var x = points[j], y = points[j + 1], b = points[j + 2];
                if (x == null)
                    continue;

                // for a bar graph, the cursor must be inside the bar
                if (series[i].bars.horizontal ?
                    (mx <= Math.max(b, x) && mx >= Math.min(b, x) &&
                     my >= y + barLeft && my <= y + barRight) :
                    (mx >= x + barLeft && mx <= x + barRight &&
                     my >= Math.min(b, y) && my <= Math.max(b, y)))
                        item = [i, j / ps];
            }
        }
    }

    if (item) {
        i = item[0];
        j = item[1];
        ps = series[i].datapoints.pointsize;

        return { datapoint: series[i].datapoints.points.slice(j * ps, (j + 1) * ps),
                 dataIndex: j,
                 series: series[i],
                 seriesIndex: i };
    }

    return null;
}

If there are alternate ways of solving this problem, please let me know.

Share edited Jul 9, 2013 at 18:10 Louis93 asked Jul 9, 2013 at 17:42 Louis93Louis93 3,9219 gold badges53 silver badges94 bronze badges 3
  • 1 In case anyone else reads this and is mystified, OP is having an issue with flot – André Dion Commented Jul 9, 2013 at 18:00
  • Added an identifier in the question, thanks. – Louis93 Commented Jul 9, 2013 at 18:03
  • You should also add some code that shows everyone what you're trying to do. – André Dion Commented Jul 9, 2013 at 18:04
Add a ment  | 

3 Answers 3

Reset to default 7 +100

What's your use case for this? If you increase the mouseActiveRadius option to something large flot will find the closest point to the cursor for you.

var options = {
    grid: { 
        hoverable: true, 
        mouseActiveRadius: 1000
    }
}

Example here.

EDIT

Yes, you can use the plothover event to retrieve the highlighted point.

$("#placeholder").bind("plothover", function (event, pos, item) {
    if (item){
        var x = item.datapoint[0].toFixed(2),
            y = item.datapoint[1].toFixed(2);
        console.log("x:" + x + ", " + "y:" + y);
    }
});

Updated Fiddle here.

That's an internal function of flot, but you can easily recreate the same functionality yourself. All you need to do is iterate through the points in your data series and pare their location to your mouse pointer (Pythagoras should be able to help you here).

As for the reason why you see: ReferenceError: findNearbyItem is not defined see this. Applying this little patch by hand will make function public.

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744822681a4595711.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信