w3schools tag tab style page for color javascript d3.js transition

javascript - tag - title of page html



Invocar una devoluciĆ³n de llamada al final de una transiciĆ³n (8)

Ahora, en d3 v4.0, hay una función para vincular explícitamente los manejadores de eventos a las transiciones:

https://github.com/d3/d3-transition#transition_on

Para ejecutar el código cuando se ha completado una transición, todo lo que necesita es:

d3.select("#myid").transition().style("opacity", "0").on("end", myCallback);

Necesito hacer un método FadeOut (similar a jQuery) usando D3.js Lo que tengo que hacer es establecer la opacidad en 0 usando transition() .

d3.select("#myid").transition().style("opacity", "0");

El problema es que necesito una devolución de llamada para darme cuenta cuando la transición haya terminado. ¿Cómo puedo implementar una devolución de llamada?


Desea escuchar el evento "final" de la transición.

d3.select("#myid").transition().style("opacity","0").each("end", myCallback);

  • Esta demostración utiliza el evento "final" para encadenar muchas transiciones en orden.
  • El ejemplo de dona que se envía con D3 también usa esto para encadenar varias transiciones.
  • Aquí está mi propia demostración que cambia el estilo de los elementos al inicio y al final de la transición.

De la documentación para transition.each([type],listener) :

Si se especifica type , agrega un detector para eventos de transición, que admite eventos tanto "inicio" como "final". El oyente se invocará para cada elemento individual en la transición, incluso si la transición tiene un retraso y una duración constantes. El evento de inicio se puede utilizar para activar un cambio instantáneo a medida que cada elemento comienza a hacer la transición. El evento final se puede usar para iniciar transiciones de varias etapas seleccionando el elemento actual, this y derivando una nueva transición. Las transiciones creadas durante el evento final heredarán la ID de transición actual y, por lo tanto, no anularán una transición más nueva que se programó previamente.

Vea este hilo del foro sobre el tema para más detalles.

Finalmente, tenga en cuenta que si solo desea eliminar los elementos después de que se hayan desvanecido (una vez que la transición ha finalizado), puede usar transition.remove() .


En realidad, hay una forma más de hacerlo utilizando temporizadores.

var timer = null, timerFunc = function () { doSomethingAfterTransitionEnds(); }; transition .each("end", function() { clearTimeout(timer); timer = setTimeout(timerFunc, 100); });


La solution Mike Bostock mejorada por kashesandr + pasando argumentos a la función de devolución de llamada:

function d3_transition_endall(transition, callback, arguments) { if (!callback) callback = function(){}; if (transition.size() === 0) { callback(arguments); } var n = 0; transition .each(function() { ++n; }) .each("end", function() { if (!--n) callback.apply(this, arguments); }); } function callback_function(arguments) { console.log("all done"); console.log(arguments); } d3.selectAll("g").transition() .call(d3_transition_endall, callback_function, "some arguments");


La solution Mike Bostock para v3 con una pequeña actualización:

function endall(transition, callback) { if (typeof callback !== "function") throw new Error("Wrong callback in endall"); if (transition.size() === 0) { callback() } var n = 0; transition .each(function() { ++n; }) .each("end", function() { if (!--n) callback.apply(this, arguments); }); } d3.selectAll("g").transition().call(endall, function() { console.log("all done") });


La siguiente es otra versión de la solution de Mike Bostock e inspirada por el comentario de @hughes a la respuesta de @ kashesandr. Realiza una única devolución de llamada al finalizar la transition .

Dada una función de drop ...

function drop(n, args, callback) { for (var i = 0; i < args.length - n; ++i) args[i] = args[i + n]; args.length = args.length - n; callback.apply(this, args); }

... podemos extender d3 así:

d3.transition.prototype.end = function(callback, delayIfEmpty) { var f = callback, delay = delayIfEmpty, transition = this; drop(2, arguments, function() { var args = arguments; if (!transition.size() && (delay || delay === 0)) { // if empty d3.timer(function() { f.apply(transition, args); return true; }, typeof(delay) === "number" ? delay : 0); } else { // else Mike Bostock''s routine var n = 0; transition.each(function() { ++n; }) .each("end", function() { if (!--n) f.apply(transition, args); }); } }); return transition; }

Como un JSFiddle .

Use transition.end(callback[, delayIfEmpty[, arguments...]]) :

transition.end(function() { console.log("all done"); });

... o con un retraso opcional si la transition está vacía:

transition.end(function() { console.log("all done"); }, 1000);

... o con argumentos de callback opcionales:

transition.end(function(x) { console.log("all done " + x); }, 1000, "with callback arguments");

d3.transition.end aplicará la callback pasada incluso con una transition vacía si se especifica el número de milisegundos o si el segundo argumento es verdadero. Esto también enviará cualquier argumento adicional a la callback (y solo esos argumentos). Es importante destacar que esto no aplicará de forma predeterminada la callback si la transition está vacía, lo que probablemente sea una suposición más segura en ese caso.


Resolví un problema similar al establecer una duración en las transiciones usando una variable. Luego usé setTimeout() para llamar a la siguiente función. En mi caso, quería una ligera superposición entre la transición y la próxima llamada, como verán en mi ejemplo:

var transitionDuration = 400; selectedItems.transition().duration(transitionDuration).style("opacity", .5); setTimeout(function () { sortControl.forceSort(); }, (transitionDuration * 0.75));


Un enfoque ligeramente diferente que también funciona cuando hay muchas transiciones con muchos elementos que se ejecutan simultáneamente:

var transitions = 0; d3.select("#myid").transition().style("opacity","0").each( "start", function() { transitions++; }).each( "end", function() { if( --transitions === 0 ) { callbackWhenAllIsDone(); } });