Você deseja ouvir o evento de "fim" da transição.
// d3 v5
d3.select("#myid").transition().style("opacity","0").on("end", myCallback);
// old way
d3.select("#myid").transition().style("opacity","0").each("end", myCallback);
Da documentação para transition.each([type],listener)
:
Se o tipo for especificado, adiciona um ouvinte para eventos de transição, suportando eventos de "início" e "término". O ouvinte será chamado para cada elemento individual na transição, mesmo se a transição tiver um atraso e uma duração constantes. O evento de início pode ser usado para acionar uma mudança instantânea conforme cada elemento começa a fazer a transição. O evento final pode ser usado para iniciar transições de vários estágios selecionando o elemento atual this
, e derivando uma nova transição. Todas as transições criadas durante o evento de término herdarão o ID de transição atual e, portanto, não substituirão uma transição mais recente que foi agendada anteriormente.
Veja este tópico do fórum sobre o tópico para mais detalhes.
Finalmente, observe que se você quiser apenas remover os elementos depois que eles desaparecerem (após o término da transição), você pode usar transition.remove()
.
d3.selectAll()
(em vez de depois que cada elemento termina)? Em outras palavras, quero apenas retornar uma função de retorno quando todos os elementos terminarem a transição..each
ouvinte de evento, nem o"end"
evento. Não parece "encadear" as transições. O segundo link aponta para um github que não carrega para mim.Solução de Mike Bostock para v3 com uma pequena atualização:
fonte
if (transition.size() === 0) { callback(); }
function endall(transition, callback){ if(!callback) return; // ... }
ou, visto que é certamente um erro chamar esta função sem um retorno de chamada, lançando uma exceção parece seja a maneira apropriada de lidar com a situação Eu acho que este caso não precisa de muito complicado Exceçãofunction endall(transition, callback){ if(!callback) throw "Missing callback argument!"; // .. }
enter()
eexit()
transições e queremos esperar até que as três tenham terminado, precisamos colocar o código no retorno de chamada para ter certeza de que ele foi chamado três vezes, certo? D3 é tão bagunçado! Eu gostaria de ter escolhido outra biblioteca.Agora, no d3 v4.0, há um recurso para anexar explicitamente manipuladores de eventos às transições:
https://github.com/d3/d3-transition#transition_on
Para executar o código quando uma transição for concluída, tudo que você precisa é:
fonte
transition.remove()
( link ), que lida com um caso de uso comum de transição de um elemento da visualização: `" Para cada elemento selecionado, remove o elemento quando a transição termina, desde que o elemento não tenha outras transições ativas ou pendentes. elemento tem outras transições ativas ou pendentes, não faz nada. "Uma abordagem um pouco diferente que funciona também quando há muitas transições com muitos elementos, cada uma funcionando simultaneamente:
fonte
A seguir está outra versão da solução de Mike Bostock e inspirada no comentário de @hughes à resposta de @kashesandr. Ele faz um único retorno de chamada ao
transition
finalizar.Dada uma
drop
função ...... podemos estender
d3
assim:Como um JSFiddle .
Use
transition.end(callback[, delayIfEmpty[, arguments...]])
:... ou com um atraso opcional se
transition
estiver vazio:... ou com
callback
argumentos opcionais :d3.transition.end
aplicará o passadocallback
mesmo com um vaziotransition
se o número de milissegundos for especificado ou se o segundo argumento for verdadeiro. Isso também encaminhará quaisquer argumentos adicionais para ocallback
(e apenas esses argumentos). É importante notar que, por padrão , isso não se aplicará acallback
iftransition
está vazio, o que provavelmente é uma suposição mais segura nesse caso.fonte
A partir do D3 v5.8.0 +, agora existe uma maneira oficial de fazer isso usando
transition.end
. Os documentos estão aqui:https://github.com/d3/d3-transition#transition_end
Um exemplo prático de Bostock está aqui:
https://observablehq.com/@d3/transition-end
E a ideia básica é que apenas acrescentando
.end()
, a transição retornará uma promessa que não será resolvida até que todos os elementos tenham concluído a transição:Consulte as notas de lançamento da versão para ainda mais:
https://github.com/d3/d3/releases/tag/v5.8.0
fonte
A solução de Mike Bostock melhorada por kashesandr + passando argumentos para a função de retorno de chamada:
fonte
Na verdade, há mais uma maneira de fazer isso usando temporizadores.
fonte
Resolvi um problema semelhante definindo uma duração nas transições usando uma variável. Então eu costumava
setTimeout()
chamar a próxima função. No meu caso, eu queria uma ligeira sobreposição entre a transição e a próxima chamada, como você verá no meu exemplo:fonte