2012-02-14 17 views
5

Ho scritto un plug-in per i grafici jQuery Flot che consente di aggiungere dinamicamente punti dati facendo clic sulla linea di un grafico, rimuoverli facendo clic con il pulsante destro del mouse e consente anche il trascinamento di questi punti attorno alla tela.Diagramma di flusso: come attivare un evento sulla linea hover

Questo funziona e ho anche un suggerimento che mostra il valore Y quando si passa con il mouse sopra o si trascina un punto.

Quello che mi piacerebbe fare è visualizzare un secondo suggerimento quando un utente si posiziona su una linea che mostra il messaggio "Fai clic con il pulsante sinistro del mouse per aggiungere un punto dati".

Non riesco a trovare un modo per aggiungere un evento hover alla linea stessa e non sembra essere un metodo nativo.

Qualcuno sa come potrei fare per raggiungere questo obiettivo?

Grazie.

EDIT: ecco un jsFiddle che include il codice di creazione tooltip che sto usando:

jsFiddle

come si può vedere un suggerimento rende quando si passa sopra un punto dati reale, tuttavia vorrei trovare un modo per sparare ha un tooltip separato reso quando si passa con il mouse sopra la linea tra i punti. NOTA: questo violino NON include il mio codice personalizzato per aggiungere e trascinare dinamicamente i datapoints in quanto sarebbe troppo codice per gli scopi di questa domanda.

+0

in che modo l'utente passa con il mouse su un suggerimento? il tooltip non sparirà quando ti focalizzi fuori dal controllo? Se mostri un esempio, ti posso aiutare –

+0

Il tooltip per un punto dati viene reso utilizzando l'evento "plothover" nativo di flot che si attiva quando un utente passa su un punto dati. Non sembra esserci alcun evento del genere per la linea stessa però. Un esempio sarebbe post difficile in quanto è strettamente integrato nell'app che sto sviluppando. Vedrò cosa posso fare comunque. – gordyr

+0

anche un jsfiddle lo farà, ma capisco che potrebbe essere difficile –

risposta

5

Quindi, in pratica, stiamo cercando di visualizzare in modo condizionale un suggerimento quando la posizione del cursore soddisfa il requisito che si trovi sopra una linea sul grafico. Poiché le linee non sono un'entità con cui possiamo lavorare, è necessario calcolare la linea tra i due punti più vicini su entrambi i lati del cursore e verificare se la posizione corrente si trova su di essa. Ho semplificato il vostro esempio un po ':

Funzione per calcolare la distanza tra due punti:

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

Supponendo che il più vicino due punti sono A e B per il cursore C allora la distanza deve essere uguale ABAC + BC.

Quindi per determinare se è sulla linea: Math.abs(AB-(AC+BC)) < SomeThreshold. Usando la soglia si disegna essenzialmente un riquadro attorno alla linea nella quale il cursore può cadere.

Poi estendere il codice nelle 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(''); 
      } 
     } 
    }); 

Le cose non fatto qui:

  1. Controllare i casi limite in modo più appropriato - quanto sopra assume il primo e l'ultimo punto sono sul bordi del grafico.
  2. Aggiungi indietro nel secondo grafico
  3. Migliora le prestazioni di ricerca dei set di dati utilizzando un approccio come bubblesort per trovare gli indici prima/dopo.
  4. Si noti che sto ridimensionando l'asse x di 10000. I numeri erano troppo grandi e nel grande divario tra i primi due punti le differenze dell'asse y erano insignificanti (il risultato era sempre zero tra questi due punti).

Nota, l'aggiunta del secondo grafico richiede di trovare i punti più vicini per entrambi i grafici e di verificare se cade su entrambe le linee. Se le tue linee sono vicine o intersecanti, puoi semplicemente creare una linea di priorità. Se tenti di aggiungere nuovamente la seconda linea, posso aiutarti in seguito.

+0

Non sapevo quanti anni aveva questa domanda. È stato comunque un problema divertente da risolvere: spero che sia ancora utile a qualcuno. – Matthew

+0

Grazie, è davvero d'aiuto! –

Problemi correlati