2012-12-12 10 views
12

Abstrakcje D3 nadal sprawiają, że mój umysł się wygina, więc mam nadzieję, że przedstawiam to poprawnie.Jaki jest standardowy sposób uzyskania aktywnej (działającej) przejścia D3 v3 dla danego elementu?

W D3 wersja 3, biorąc pod uwagę element (słownie okręgu), a given only one transition possibly running per element co jest najlepszym sposobem, aby ustalić, co obecny bieg na przejście tego elementu jest, jeśli istnieje w ogóle?

Jestem świadomy, że mogę ręcznie sprawdzić __transition__ na elemencie (choć pomoc jest również mile widziany), ale naprawdę mam nadzieję na coś nieco wyższego poziomu.

Moim głównym celem tutaj jest stworzenie subtransition jeśli-i-tylko-jeśli jest przejście do sub. W przeciwnym razie stworzę nowe przejście.

+0

Czy możesz określić, czy mówisz o v2 czy v3? – Wex

+0

Powiedziałem wersję 3, ale może powinienem pogrubić to lub coś .. – Chuck

+0

Inspekcja \ _transition_ jest prawdopodobnie najbardziej skutecznym sposobem, aby to zrobić. Właściwość \ _transition_ jest usuwana po zakończeniu przejścia elementu, więc możesz po prostu sprawdzić, czy właściwość \ _transition_ jest obecna. Jeśli tak, to wiesz, że nastąpiło przejście na ten element i możesz sprawdzić \ _transition_, aby uzyskać bardziej szczegółowe informacje. Masz również opcje przechwytywania podelementów elementu przejściowego, takich jak using transition.selectAll(). Można również dodać detektory do każdego elementu w trakcie przejścia za pomocą funkcji transition.each() –

Odpowiedz

2

Krótka odpowiedź brzmi, że nie ma standardowego sposobu na przejście i nie ma na to ochoty. W tej wersji nie jest obsługiwany.

Trochę dłuższa odpowiedź brzmi: prawdopodobnie zhakujesz ją za pomocą __transition__. Chodzi o sprawdzenie, czy istnieje __transition__, a jeśli tak, to poczekaj, aż nie zacznie się przed rozpoczęciem nowego (pod) przejścia.

Aby to zrobić, pomaga przedłużyć prototyp wyboru z odpowiednią funkcję:

d3.selection.prototype.getTransition = function() { 
    if(this[0][0].__transition__) { 
    return this[0][0].__transition__[1]; 
    } else return undefined; 
} 

Zauważ, że to tutaj jest bardzo hacky i będzie tylko praca czy istnieje dokładnie jeden element wybór z dokładnie jednym przejściem. Powinieneś jednak wpaść na pomysł.

Teraz możemy użyć tej funkcji do określenia, czy przejście jest uruchomione.

if(sel.getTransition() !== undefined) { 
    // transition is there 
} else { 
    // no transition 
} 

Niestety __transition__ nie pozwalają zrekonstruować obiekt przejściowy, tj dodaje nie będzie działać.

sel.getTransition().transition()... 

więc symulować subtransition który rozpoczyna się po aktualnie uruchomiony jeden jest kompletny, należy setTimeout, by sprawdzić, czy coś działa i tak szybko, jak nic nie jest, rozpocząć nowe przejścia:

function check() { 
    if(sel.getTransition() !== undefined) { 
    setTimeout(check, 100); 
    } else { 
    sel.transition().duration(1000)...; 
    } 
} 
check(); 

ty może zredukować interwał między kontrolami (tutaj 100ms), aby stworzyć lepsze wrażenie przejścia, które następuje zaraz po poprzednim.

Pełny przykład here. Zauważ, że prawie we wszystkich przypadkach znacznie łatwiej jest zachować odniesienie do obiektu przejściowego i używać go. Ten przykład naprawdę służy jedynie jako hackowaty dowód koncepcji.

+1

Interesujący problem. Możesz uczynić go nieco bardziej efektywnym, używając właściwości obiektu '__transition __ [1]', aby dokładnie obliczyć, kiedy zakończy się bieżące przejście, i odpowiednio ustawić czas oczekiwania: http://jsfiddle.net/7SQBe/1/ – AmeliaBR

3

Inny sposób: Utwórz własną właściwość w każdym węźle, który przechowuje tablicę rzeczywistych obiektów d3.transition. Podczas tworzenia nowego przejścia, weź ostatnie przejście z tablicy i utwórz przejście pomocnicze.

Powoduje to, że nowe przejście może nie być oparte na tym samym wyborze, co aktywne przejście.Dlatego tworzę nowe "bezpieczne" przejścia dla każdego elementu w ramach połączenia .each().

function saveTransition(t) { 
    //save the transition immediately (don't wait for "start") 
    //clear it on "end" 
    t.each(function() { 
     var tArr = this.__tObj__ 
     if (!tArr) tArr = this.__tObj__ = []; 

     tArr.push(t); 
     //console.log("saving ", t, " for ",this); 
     }) 
    .each("end", function() { 
     var test = this.__tObj__.shift(); 
     // console.log("clearing ", t, " from " ,this, 
     //   (test == t ? "correctly" : "ERROR")); 
     }); 
} 
function newSafeTransition(node) { 
    var tArr = node.__tObj__; 
    if (tArr && tArr.length) { 

     var t = tArr[ tArr.length - 1 ]; 
     return t.filter(function(){ return this === node; }) 
       .transition().call(saveTransition); 
    } 
    else { 
     return d3.select(node).transition().call(saveTransition); 
    } 
} 

d3.selectAll("div.foo") 
    .transition().duration(3000) 
    .call(saveTransition) 
    .style("left", "100px"); 

d3.selectAll("div.bar") 
    .transition().duration(3000) 
    .call(saveTransition) 
    .style("top", "100px"); 

setTimeout(function() { 
    console.log("blue"); 

    d3.selectAll("div.blue") 
     .each(function() { 
      newSafeTransition(this).style("color", "blue"); 
     }); 
}, 1000); 

setTimeout(function() { 
    console.log("reposition"); 

    d3.selectAll("div.foo") 
     .each(function() { 
      newSafeTransition(this).style("left", "0px"); 
     }); 
}, 2000); 

http://jsfiddle.net/7SQBe/3/

Może to prawdopodobnie być czyszczone, można nawet ponad napisać metod selection.transition() i transition.transition() to zrobić automatycznie. Prawdopodobnie jednak chcesz zachować sposób wskazywania, czy chcesz przejść do kolejnej zmiany po zaplanowanych przejściach, czy chcesz przerwać.

Powiązane problemy