2012-02-14 12 views
5

He escrito un plugin para los gráficos de jQuery Flot, que le permite añadir dinámicamente puntos de datos haciendo clic en la línea de un gráfico, eliminarlos haciendo clic derecho y también permite el arrastre de estos puntos alrededor del lienzo.tabla Flot - cómo se disparó el evento en línea de vuelo estacionario

Esto funciona bien y también tengo una información sobre herramientas que muestra el valor de Y cuando se pasa sobre o arrastrar un punto alrededor.

Lo que me gustaría hacer es mostrar una segunda información de herramientas cuando un usuario se desplaza sobre una línea que muestra el mensaje "Haga clic izquierdo para agregar un punto de datos".

Me parece que no puede encontrar una manera de añadir un evento de vuelo estacionario a la línea de sí mismo y no parece ser un método nativo.

¿Alguien sabe cómo puedo lograr esto?

Gracias.

EDIT: aquí hay una jsFiddle que incluye el código de creación de información sobre herramientas que estoy utilizando:

jsFiddle

como se puede ver un texto de ayuda renders cuando se pasa sobre un punto de datos real, sin embargo me gustaría encuentre una manera de disparar, tenga una información sobre herramientas separada cuando pase el cursor sobre la línea entre los puntos de datos. NOTA: este violín NO incluye mi código personalizado para agregar y arrastrar dinámicamente los puntos de datos, ya que sería demasiado código para los propósitos de esta pregunta.

+0

¿cómo se desplaza el usuario sobre una información sobre herramientas? ¿no desaparecerá la información sobre herramientas cuando te concentres fuera del control? Si muestra un ejemplo, podría ayudarlo –

+0

La información sobre herramientas para un punto de datos se representa mediante el uso del evento nativo "plothover" de flot, que se activa cuando un usuario se desplaza sobre un punto de datos. Sin embargo, no parece haber tal evento para la línea en sí. Un ejemplo sería difícil ya que está estrechamente integrado en la aplicación que estoy desarrollando. Veré lo que puedo hacer sin embargo. – gordyr

+0

incluso un jsfiddle servirá, pero entiendo que podría ser difícil –

Respuesta

5

Así que básicamente estamos buscando para condicionalmente mostrar un texto de ayuda cuando la posición del cursor cumple con el requisito de que es más de una línea en la tabla. Dado que las líneas no son una entidad con la que podamos trabajar, es necesario calcular la línea entre los dos puntos más cercanos a cada lado del cursor y luego ver si su posición actual se encuentra en ella. Que simplifica tu ejemplo un poco:

función para calcular la distancia entre dos puntos:

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

Suponiendo que sus dos puntos más próximos son A y B para el cursor C, entonces la distancia debe ser igual a ABAC + BC.

Para determinar si está en la línea: Math.abs(AB-(AC+BC)) < SomeThreshold. El uso del umbral esencialmente dibuja un cuadro alrededor de la línea en la que puede caer el cursor.

A continuación, la ampliación de su código en los 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(''); 
      } 
     } 
    }); 

cosas no hecho aquí:

  1. Verificar los casos de borde más apropiadamente - lo anterior supone el primer y último puntos están en el bordes del gráfico.
  2. Agregue en su segundo gráfico
  3. Mejore el rendimiento de búsqueda del conjunto de datos utilizando un enfoque como bubblesort para encontrar los índices de antes/después.
  4. en cuenta que estoy reducción a escala del eje x por 10000. Los números eran demasiado grandes y en la gran brecha entre los dos primeros puntos hizo que las diferencias insignificantes eje Y (el resultado fue siempre cero entre estos dos puntos).

Nota: si agrega el segundo gráfico, necesitará buscar los puntos más cercanos para ambos gráficos y comprobar si se trata de una línea. Si sus líneas están cerca o se cruzan, podría simplemente hacer una línea de prioridad. Si le cuesta agregar la segunda línea, puedo ayudarlo más tarde.

+0

No me di cuenta de la edad de esta pregunta. Aunque fue un problema divertido de resolver, espero que todavía sea útil para alguien. – Matthew

+0

¡Gracias, eso realmente ayuda! –

Cuestiones relacionadas