2013-06-13 3 views
18

Używam V3 popularnej biblioteki d3 i zasadniczo chcę mieć trzy przejścia, a następnie jeden nawzajem: Pierwsze przejście powinno dotyczyć wyboru wyjścia, drugie do aktualizacji wybór i trzeci wybór. Powinny być one powiązane w taki sposób, że gdy jedno z wyborów jest puste, odpowiednie przejście jest pomijane. To znaczy. gdy nie ma wyjścia, wybór aktualizacji powinien rozpocząć się natychmiast. Do tej pory wymyśliłem ten kod (używając funkcji delay).d3: Jak prawidłowo łańcuch przejść na różne wybory

// DATA JOIN 
var items = d3.select('#data').selectAll('.item'); 
items = items.data(data, function(d){ 
    return d.twitter_screenname; 
}); 


// EXIT 
items.exit().transition().duration(TRANSITION_DURATION).style('opacity', 0).remove(); 

// UPDATE 
// Divs bewegen 
items.transition().duration(TRANSITION_DURATION).delay(TRANSITION_DURATION * 1) 
    .style('left', function(d, i) { 
     return positions[i].left + "px"; 
    }).style('top', function(d, i) { 
     return positions[i].top + "px"; 
    }); 

// ENTER 
// Divs hinzufügen 
var div = items.enter().append('div') 
    .attr('class', 'item') 
    .style('left', function(d, i) { 
     return positions[i].left + "px"; 
    }).style('top', function(d, i) { 
     return positions[i].top + "px"; 
    }); 

div.style('opacity', 0) 
    .transition().duration(TRANSITION_DURATION).delay(TRANSITION_DURATION * 2) 
    .style('opacity', 1); 

Przede wszystkim nie dopuszczać do „skip” przejścia i po drugie myślę, że jest lepszy sposób niż delay. Spoglądałem na http://bl.ocks.org/mbostock/3903818, ale tak naprawdę nie rozumiałem, co się dzieje.

Ponadto, po prostu pisanie items.exit().transition().duration(TRANSITION_DURATION).remove() nie działa z items, prawdopodobnie dlatego, że nie są elementami SVG, ale div s.

Odpowiedz

30

Pewnie. Oto dwa sposoby.

Po pierwsze, można użyć jawnego delay, który następnie można obliczyć, używając selection.empty, aby pominąć puste przejścia. (Jest to tylko drobne modyfikacje, co już masz.)

var div = d3.select("body").selectAll("div") 
    .data(["enter", "update"], function(d) { return d || this.textContent; }); 

// 2. update 
div.transition() 
    .duration(duration) 
    .delay(!div.exit().empty() * duration) 
    .style("background", "orange"); 

// 3. enter 
div.enter().append("div") 
    .text(function(d) { return d; }) 
    .style("opacity", 0) 
    .transition() 
    .duration(duration) 
    .delay((!div.exit().empty() + !div.enter().empty()) * duration) 
    .style("background", "green") 
    .style("opacity", 1); 

// 1. exit 
div.exit() 
    .style("background", "red") 
    .transition() 
    .duration(duration) 
    .style("opacity", 0) 
    .remove(); 

http://bl.ocks.org/mbostock/5779682

Jeden trudne rzeczą jest to, że trzeba utworzyć przejście na elementach aktualizujących przed tworzą przejście na elementy wprowadzające; to dlatego, że enter.append scala wprowadzanie elementów do selekcji aktualizacji i chcesz zachować je oddzielnie; szczegółowe informacje znajdują się w Update-only Transition example.

Alternatywnie można użyć transition.transition do chain transitions i transition.each, aby zastosować te powiązane przejścia do istniejących wyborów. W kontekście transition.each, selection.transition dziedziczy istniejące przejście, zamiast tworzyć nowe.

var div = d3.select("body").selectAll("div") 
    .data(["enter", "update"], function(d) { return d || this.textContent; }); 

// 1. exit 
var exitTransition = d3.transition().duration(750).each(function() { 
    div.exit() 
     .style("background", "red") 
    .transition() 
     .style("opacity", 0) 
     .remove(); 
}); 

// 2. update 
var updateTransition = exitTransition.transition().each(function() { 
    div.transition() 
     .style("background", "orange"); 
}); 

// 3. enter 
var enterTransition = updateTransition.transition().each(function() { 
    div.enter().append("div") 
     .text(function(d) { return d; }) 
     .style("opacity", 0) 
    .transition() 
     .style("background", "green") 
     .style("opacity", 1); 
}); 

http://bl.ocks.org/mbostock/5779690

Przypuszczam, że ten ostatni jest nieco bardziej idiomatyczne, chociaż przy użyciu transition.each zastosować przejścia do wyboru (zamiast czerpać przejścia z domyślnymi parametrami) nie jest szeroko znana cecha.

+0

Popraw mnie, jeśli się mylę, ale myślę, że jest mały błąd w twoim kodzie za pomocą 'delay()' -Method. Kiedy nie ma przejścia aktualizacji (tzn. Żadne elementy nie zmieniają miejsca), 'items.enter(). Empty()' nadal jest równe 'false', więc elemens kończy pracę, a następnie, przez 'czas trwania' milisekund nic się nie dzieje, a następnie przejście do wprowadzania zaczyna się. Ale jeśli nie ma przejścia do aktualizacji wizualnej, chcę, aby przejście do wyjścia było * natychmiast * realizowane przez przejście do wprowadzania. W ten sposób zapisuję przejście aktualizacji w następujący sposób: – wnstnsmth

+0

'var updatedItems = div.transition() .duration (duration) .delay (! Div.exit(). Empty() * duration)' i zmień '.delay ((! div.exit(). empty() +! div.enter(). empty()) * duration) 'do' .delay ((! div.exit(). empty() +! updatedItems.empty()) * czas trwania) '. W ten sposób działa zgodnie z wymaganiami. – wnstnsmth

Powiązane problemy