2012-05-02 8 views
9

Ho implementato un semplice grafico a linee D3.js che può essere ingrandito e ridotto. È basato sull'eccellente esempio di Stephen Bannasch here.Limitazione del dominio durante lo zoom o il panning in D3.js

Il dominio dei miei dati è [0, n] nella dimensione x.

Come limitare lo zoom e la panoramica a questo dominio utilizzando il comportamento dello zoom incorporato (ad esempio, utilizzando gli eventi della rotellina del mouse)?

Voglio impedire agli utenti di effettuare il panning oltre 0 nella parte inferiore o n nella parte superiore, ad esempio non dovrebbero mai essere in grado di visualizzare valori negativi sull'asse x e si desidera limitare lo zoom alla stessa finestra .

Gli esempi che ho trovato basati su Jason Davies funzionano con estensione ([...], [...], [...]) sembrano non funzionare più nella versione 2.9.1. Sfortunatamente, il comportamento dello zoom è attualmente una delle poche funzionalità non documentate nella documentazione API in sospeso.

Qualsiasi suggerimento è benvenuto.

PS. Ho postato la stessa domanda sulla mailing list D3.js ma non ho ricevuto risposta: https://groups.google.com/d/topic/d3-js/w6LrHLF2CYc/discussion. Mi scuso per il cross-posting.

risposta

0

Hai solo bisogno di limitare il dominio sul ridisegno. Il codice seguente impedirà al grafico di essere ingrandito oltre i suoi domini iniziali (come utilizzato in http://bl.ocks.org/1182434).

SimpleGraph.prototype.redraw = function() { 
    var self = this; 
    return function() { 

    self.x.domain([Math.max(self.x.domain()[0], self.options.xmin), Math.min(self.x.domain()[1], self.options.xmax)]); 

    self.y.domain([Math.max(self.y.domain()[0], self.options.ymin), Math.min(self.y.domain()[1], self.options.ymax)]); 

    .... 
+1

So che questo post è vecchio, ma FYI: il collegamento di riferimento mi consente di ridurre lo zoom e visualizzare il contenuto del mio cuore. (Chrome 29.0) – SgtPooki

+0

Tuttavia, il tuo codice funziona con il mio grafico. Saluti. – SgtPooki

+1

Il grafico si ingrandisce durante la panoramica usando questo esempio. –

6

Purtroppo, la soluzione postato da Bill ha fatto solo la metà il trucco: Anche se in effetti inibire la panning, che provoca il grafico di falsare se si applica lo zoom. Di solito è impossibile tornare a un grafico correttamente proporzionato e posizionato.

Nella seguente versione vengono mantenute le proporzioni degli assi, anche se si scorre verso i bordi.

Non appena il ridimensionamento raggiunge il 100%, i domini delle scale vengono riportati alla loro posizione originale. Ciò garantisce un posizionamento corretto, anche se i passi intermedi restituiscono parametri non validi per gli assi.

Anche se non perfetto, spero che questo script possa aiutare qualcuno fino a quando d3 (re) implementa questa funzione.

# x and y are the scales 
# xAxis and yAxis are the axes 
# graph is the graph you want attach the zoom to 

x0 = x.copy() 
y0 = y.copy() 

successfulTranslate = [0, 0] 

zoomer = d3.behavior.zoom() 
    .scaleExtent([1,2]) 

onZoom = -> 
    ev = d3.event # contains: .translate[x,y], .scale 
    if ev.scale == 1.0 
    x.domain x0.domain() 
    y.domain y0.domain() 
    successfulTranslate = [0, 0] 
    else 
    xTrans = x0.range().map((xVal) -> (xVal-ev.translate[0])/ev.scale).map(x0.invert) 
    yTrans = y0.range().map((yVal) -> (yVal-ev.translate[1])/ev.scale).map(y0.invert) 
    xTransOk = xTrans[0] >= x0.domain()[0] and xTrans[1] <= x0.domain()[1] 
    yTransOk = yTrans[0] >= y0.domain()[0] and yTrans[1] <= y0.domain()[1] 
    if xTransOk 
     x.domain xTrans 
     successfulTranslate[0] = ev.translate[0] 
    if yTransOk 
     y.domain yTrans 
     successfulTranslate[1] = ev.translate[1] 
    zoomer.translate successfulTranslate 

graph.select('g.x.axis').call(xAxis) 
graph.select('g.y.axis').call(yAxis) 
drawBars() 

zoomer.on('zoom', onZoom) 

# ... 
graph.call(zoomer) 
+1

Quasi perfetto. Il problema che ho avuto con questo è che non ha alcun effetto durante le azioni di zoom. Se si esegue lo zoom in avvicinamento al limite destro, posizionare il cursore sul bordo sinistro dell'area visibile e ridurre l'ingrandimento: il bordo destro dell'area visibile supererà il limite previsto. Penso che per una soluzione completa, invece di accettare/rifiutare semplicemente le modifiche alla traduzione, dovresti andare nella direzione opposta. Dai limiti di dominio calcola l'intervallo legale di traduzione e limita i valori di traduzione. – mdaoust

Problemi correlati