2015-11-09 10 views
5

sto ottenendo posizioni ogni 100 ms e applicarli al DOM in questo modo:valori di transizione entrare in D3

const div = d3.select(container).selectAll('div').data(positions) 

div.enter() 
    .append('div') 

div.transition() 
    .duration(100) 
    .style({ 
    top: d => d.y, 
    left: d => d.x, 
    }) 

div.exit() 
    .remove() 

Così gli elementi ottenere un'animazione fluida alle nuove posizioni nei 100ms che ci vuole per ottenere il prossime posizioni. Funziona bene

Ma ho diversi elementi nel DOM che dipendono dalla posizione dei primi elementi. Sono resi con gli stessi dati di posizione, ma in un modulo diverso del software.

Il mio problema è che questa transizione interpola dati che non sono disponibili per gli altri moduli. Gli elementi di questi altri moduli sembrano fornire visualizzazioni "otticamente sbagliate", perché si basano sui dati grezzi.

Esempio: un punto si sposta in un quadrato e il quadrato viene evidenziato, ma la posizione del punto viene interpolata e la posizione utilizzata dal quadrato per controllare se deve essere evidenziata non lo è. Quindi il quadrato viene evidenziato anche se il punto non è al suo interno.

Come aggirare questo? Posso afferrare quei valori interpolati da qualche parte?

risposta

2

Se ti sto comprensione correttamente, si vuole prendere il controllo completo della funzione di interpolazione:

div 
    .transition() 
    .duration(1000) 
    .tween("postion", function(d) { 
     var div = d3.select(this), 
     startTop = parseInt(div.style('top')), 
     startLeft = parseInt(div.style('left')), 
     yInterp = d3.interpolateRound(startTop, d.y), 
     xInterp = d3.interpolateRound(startLeft, d.x); 
     return function(t) {    
     div.style("top", yInterp(t) + "px"); 
     div.style("left", xInterp(t) + "px"); 
     }; 
    }); 

codice di lavoro:

<!DOCTYPE html> 
 
<html> 
 

 
    <head> 
 
    <script data-require="[email protected]" data-semver="3.5.3" src="//cdnjs.cloudflare.com/ajax/libs/d3/3.5.3/d3.js"></script> 
 
    </head> 
 

 
    <body> 
 
    <div id="parent"> 
 
     <div style="width: 20px; top: 20px; left: 30px; height: 20px; background-color: steelblue; position: absolute"></div> 
 
     <div style="width: 20px; top: 0px; left: 40px; height: 20px; background-color: orange; position: absolute"></div> 
 
    </div> 
 
    <script> 
 
    
 
     var positions = [ 
 
     {x: 50, y: 50}, 
 
     {x: 100, y: 100} 
 
     ]; 
 
    
 
     var div = d3.select('#parent') 
 
     .selectAll('div') 
 
     .data(positions); 
 

 
     div 
 
     .transition() 
 
     .duration(1000) 
 
     .tween("postion", function(d) { 
 
      var div = d3.select(this), 
 
      startTop = parseInt(div.style('top')), 
 
      startLeft = parseInt(div.style('left')), 
 
      yInterp = d3.interpolateRound(startTop, d.y), 
 
      xInterp = d3.interpolateRound(startLeft, d.x); 
 
      return function(t) {    
 
      div.style("top", yInterp(t) + "px"); 
 
      div.style("left", xInterp(t) + "px"); 
 
      }; 
 
     }); 
 
    </script> 
 
    </body> 
 

 
</html>

+0

Il problema è che non interpolare da 0, ma dalla vecchia posizione. Ma quando provo a selezionare il div nella funzione tween e ottengo il suo top-style, ottengo solo "auto" e non l'ultima posizione: \ –

+1

@K .., non sono sicuro di aver capito, puoi ottenere il posizioni iniziali nella funzione. Vedi gli aggiornamenti sopra. – Mark

+0

Nel tuo esempio stai usando 0, ma se lo faccio, ogni volta che 'd.x' cambia, viene interpolato da 0 non dalla sua ultima posizione. –

3

Il modo più semplice a cui riesco a pensare è quello di utilizzare i metodi attrTween, styleTween o tween della transizione (https://github.com/mbostock/d3/wiki/Transitions#attrTween). Prendono una funzione che deve restituire una funzione (interpolatore). Quell'interpolatore verrà chiamato più volte per eseguire la transizione, quindi è possibile continuare a chiamare il callback (cb) che notificherà altri moduli sulla modifica.

selection.styleTween('top', function(){ 
    var interpol = d3.interpolate(0,10); //interpolate from 0 to 10 
    return function(t) { // this guy will be called many times to calc transition 
    // t will be changing from 0 to 1 
    var val = interpol(t); 
    cb(val); // <-- callback that will notify other modules about the change in value 
    return val; // <-- you have to return val so d3 transitions element 
    } 
}); 
+0

C'è nessun modo per ottenere la transizione già in esecuzione senza implementare la mia? Ce n'è uno, mi piace, voglio solo i suoi valori. –

+1

Non ho ricevuto la tua domanda. Per favore riformulare – sergeyz

+0

Il tuo esempio con 'styleTween' mi costringe ad implementare la mia transizione con l'aiuto di' d3.interpolate() 'Ho solo sperato in una soluzione che mi permetta di usare la transizione che avevo già descritto nell'esempio e di ottenere comunque il risultato valori interpolati in qualche modo :) –

Problemi correlati