Flot chart - 如何在线悬停时触发事件

时间:2012-02-14 17:20:52

标签: jquery canvas flot

我为jQuery Flot图表编写了一个插件,它允许您通过单击图表的线条动态添加数据点,通过右键单击删除它们,并允许在画布上拖动这些点。

这很好用,当你将鼠标悬停在上面或拖动一个点时,我还有一个显示Y值的工具提示。

我想要做的是当用户将鼠标悬停在显示消息的行上时显示第二个工具提示"左键单击以添加数据点"。

我似乎无法找到一种方法来向行本身添加悬停事件,并且它似乎不是本机方法。

有谁知道如何实现这个目标?

谢谢。

编辑:这是一个包含我正在使用的工具提示创建代码的jsFiddle:

jsFiddle

当你将鼠标悬停在一个实际的数据点上时,你可以看到一个工具提示渲染,但我想找到一种方法,当你将鼠标悬停在数据点之间的线上时,会有一个单独的工具提示。注意:这个小提琴不包括我的自定义代码来动态添加和拖动数据点,因为这个问题的代码太多了。

1 个答案:

答案 0 :(得分:5)

因此,当光标的位置满足要求它超出图表上的一条线时,基本上我们希望有条件地显示工具提示。由于线条不是我们可以使用的实体,因此需要计算光标两侧最近两点之间的直线,然后查看当前位置是否位于光标两侧。我简化了你的例子:

计算两点之间距离的函数:

function lineDistance( p1x, p1y,p2x, p2y ) {
    return Math.sqrt( (p2x - p1x)*(p2x - p1x) + (p2y-p1y)*(p2y-p1y) );
}

假设距离光标C最近的两个点是A和B,那么距离AB应该等于AC + BC

所以要确定它是否在线:Math.abs(AB-(AC+BC)) < SomeThreshold。使用阈值实质上是在光标可以落入其中的行周围绘制一个框。

然后在plothoverjsFiddle

中扩展您的代码
$(placeholder).bind("plothover", function (event, pos, item) {
    if (item) {
        var tipText;

        if (opts.xaxis.mode === "time" || opts.xaxes[0].mode === "time") {
            tipText = stringFormat(to.content, item, timestampToDate);
        } else {
            tipText = stringFormat(to.content, item);
        }

        $tip.html(tipText).css({
            left: tipPosition.x + to.shifts.x,
            top: tipPosition.y + to.shifts.y
            }).show();
    } else {
         // Extended for line hover
         var series = plot.getData();
         var xBeforeIndex = 0;
         var xAfterIndex = -1;
         var Threshold = 0.0000025;
         var i = 1;
         while (i <= series[0].data.length && xAfterIndex==-1) {
             if (xAfterIndex == -1 && pos.x > series[0].data[i][0]) {
                 xBeforeIndex = i;
             } else if (xAfterIndex == -1) {
                 xAfterIndex = i;
             }
             i++;
         }

         var onTheLine = 
             lineDistance(
                series[0].data[xBeforeIndex][0]/10000,series[0].data[xBeforeIndex][1], 
                pos.x/10000, pos.y)
             +lineDistance(pos.x/10000, pos.y,
                series[0].data[xAfterIndex][0]/10000,series[0].data[xAfterIndex][1])
             -lineDistance(
                series[0].data[xBeforeIndex][0]/10000,series[0].data[xBeforeIndex][1],
                series[0].data[xAfterIndex][0]/10000,series[0].data[xAfterIndex][1]);

          if (Math.abs(onTheLine) < Threshold) {
              tipText = "Found Line";
              $tip.html(tipText).css({
                  left: tipPosition.x + to.shifts.x,
                  top: tipPosition.y + to.shifts.y
                  }).show();
           } else {
               $tip.hide().html('');
           }
       }
  });

这里没有做的事情:

  1. 更合适地检查边缘情况 - 上面假设第一个和最后一个点位于图形的边缘。
  2. 在第二张图表中添加
  3. 使用像bubblesort这样的方法来改善数据集搜索性能,以找到前/后索引。
  4. 请注意,我正在缩小x轴10000.数字太大,前两点之间的差距很大,使得y轴差异无关紧要(结果在这两点之间始终为零)。
  5. 注意,添加第二个图表将要求您找到两个图形的最近点,并检查它是否落在任一行上。如果您的线条靠近或相交,您可以只设置一条优先线。如果你很难再添加第二行,我可以稍后帮忙。