tutorial examples ejemplos d3js javascript d3.js transitions

javascript - examples - ¿Cuál es la forma estándar de obtener la transición activa(en ejecución) D3 v3 para un elemento dado?



github d3 (2)

Las abstracciones de D3 todavía hacen que mi mente se doble, así que espero presentar esto correctamente.

En la versión 3 de D3, dado un elemento (por ejemplo, un círculo), y dado que solo se puede ejecutar una transición por elemento, ¿cuál es la mejor manera de determinar cuál es la transición de ejecución actual en ese elemento, si es que hay alguno?

Soy consciente de que puedo inspeccionar __transition__ manualmente en el elemento (aunque la ayuda allí también es bienvenida), pero realmente espero algo un poco más alto.

Mi objetivo más grande aquí es crear una subtransición si-y-solo-si hay una transición a sub. De lo contrario, crearé una nueva transición.


La respuesta corta es que no hay una forma estándar de obtener la transición y no se supone que hagas eso. Como en, no es compatible.

La respuesta un poco más larga es que para tus propósitos, probablemente puedas hackearla usando __transition__ . La idea es verificar si __transition__ existe y, si es así, esperar hasta que no lo haga antes de comenzar la nueva (sub) transición.

Para hacer eso, ayuda a extender el prototipo de selección con una función apropiada:

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

Tenga en cuenta que esto aquí es extremadamente hacky y solo funcionará si hay exactamente un elemento en la selección con exactamente una transición . Deberías tener la idea sin embargo.

Ahora, podemos usar esta función para determinar si se está ejecutando una transición.

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

Lamentablemente, __transition__ no le permite reconstruir el objeto de transición, es decir, lo siguiente no funcionará.

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

Entonces, para simular una subtransición que comience después de que se complete la ejecución actual, use setTimeout para verificar si algo se está ejecutando y tan pronto como nada esté setTimeout , comience su nueva transición:

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

Puede reducir el intervalo entre las comprobaciones (100 ms aquí) para crear una mejor impresión de una transición que sigue inmediatamente a la anterior.

Ejemplo completo aquí . Tenga en cuenta que en casi todos los casos, es mucho más fácil y mejor mantener una referencia al objeto de transición en algún lugar y usar eso. Este ejemplo realmente solo sirve como una prueba de concepto hacky.


Otra forma de hacerlo: crea tu propia propiedad en cada nodo que almacena una matriz de los objetos d3.transition reales. Al crear una nueva transición, tome la última transición de la matriz y cree una sub-transición.

La complicación es que su nueva transición puede no estar basada en la misma selección que la transición activa. Por lo tanto, creo las nuevas transiciones "seguras" por elemento dentro de una llamada .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/

Probablemente podría limpiarse, incluso podría sobrescribir los métodos selection.transition() y transition.transition() para hacer esto automáticamente. Sin embargo, es probable que desee mantener una forma de indicar si desea poner en cola la nueva transición después de cualquier transición programada o si desea interrumpir.