Флот-диаграмма - как запустить событие при наведении линии - PullRequest
5 голосов
/ 14 февраля 2012

Я написал плагин для диаграмм jQuery Flot, который позволяет динамически добавлять точки данных, щелкая мышью по линии диаграммы, удалять их щелчком правой кнопки мыши, а также позволяет перетаскивать эти точки по холсту.

Это работает нормально, и у меня также есть всплывающая подсказка, отображающая значение Y, когда вы наводите курсор мыши или перетаскиваете точку вокруг.

Я хотел бы отобразить вторую подсказку, когда пользователь наводит курсор на линиюпоказывая сообщение «Щелкните левой кнопкой мыши, чтобы добавить точку данных».

Я не могу найти способ добавить событие при наведении курсора на саму строку, и, похоже, нет собственного метода.

Кто-нибудь знает, как мне добиться этого?

Спасибо.

РЕДАКТИРОВАТЬ: вот jsFiddle, который включает код создания всплывающей подсказки, который я использую:

jsFiddle

, поскольку вы можете видеть подсказку, отображаемую при наведении курсора на фактическую точку данных, однако я хотел бы найти способ запустить отдельную подсказкуотображается при наведении курсора на линию между точками данных.ПРИМЕЧАНИЕ: эта скрипка НЕ ​​включает мой пользовательский код для динамического добавления и перетаскивания точек данных, поскольку для целей этого вопроса было бы слишком много кода.

1 Ответ

5 голосов
/ 12 февраля 2014

Таким образом, в основном мы хотим условно отобразить всплывающую подсказку, когда положение курсора соответствует требованию, что оно находится над линией на графике.Поскольку линии не являются сущностью, с которой мы можем работать, вам нужно вычислить линию между двумя ближайшими точками по обе стороны от курсора, а затем посмотреть, лежит ли на ней ваша текущая позиция.Я немного упростил ваш пример:

Функция для вычисления расстояния между двумя точками:

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

Предполагая, что ваши ближайшие две точки - это точки A и B до курсора C, а затем расстояние ABдолжно равняться AC + BC.

Итак, чтобы определить, находится ли он в строке: Math.abs(AB-(AC+BC)) < SomeThreshold.Использование порога, по сути, рисует рамку вокруг линии, в которую может попасть курсор.

Затем расширение вашего кода в plothover ( jsFiddle )

$(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. Улучшение производительности поиска по наборам данных с использованием подхода, подобного пузырьковой сортировке, для поиска индексов до / после.
  4. Обратите внимание, что я уменьшаю ось X на 10000. Числа были слишком большими ив большом промежутке между первыми двумя точками различия по оси Y были незначительными (результат всегда был нулевым между этими двумя точками).

Обратите внимание, добавление второго графика потребует от вас найти ближайшийуказывает на оба графика и проверяет, попадает ли он на одну из линий.Если ваши линии близки или пересекаются, вы можете сделать одну из них приоритетной.Если вы затрудняетесь добавить вторую строку, я могу помочь позже.

...