Подтвердить что ты не робот

Каков стандартный способ получения активного (запущенного) D3 v3 Transition для данного элемента?

Абстракции D3 все еще заставляют мой разум сгибаться, поэтому, надеюсь, я представляю это правильно.

В D3 версии 3, учитывая элемент (скажем, круг) и учитывая только один переход, возможно, выполняющийся на элемент. лучший способ определить, что текущий текущий переход на этот элемент, если он есть вообще?

Я знаю, что я могу вручную проверить __transition__ на элементе (хотя помощь тоже приветствуется), но я действительно надеюсь на что-то немного более высокого уровня.

Моя более крупная цель - создать субтранслирование if-and-only - если есть переход к sub. В противном случае я создам новый переход.

4b9b3361

Ответ 1

Другой способ сделать это: создать собственное свойство на каждом node, которое хранит массив фактических объектов d3.transition. При создании нового перехода возьмите последний переход из массива и создайте суб-переход.

Усложнение состоит в том, что ваш новый переход может не основываться на том же выборе, что и активный переход. Поэтому я создаю новые "безопасные" переходы на основе каждого элемента в вызове .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/

Возможно, это можно было бы очистить, вы могли бы даже переписать методы selection.transition() и transition.transition(), чтобы сделать это автоматически. Тем не менее, вы, вероятно, захотите указать способ, чтобы указать, хотите ли вы переключать новый переход после любых запланированных переходов или хотите ли вы прерывать.

Ответ 2

Короткий ответ заключается в том, что нет стандартного способа перехода, и вы не должны этого делать. Как и в, он не поддерживается.

Несколько более длинный ответ заключается в том, что для ваших целей вы можете взломать его с помощью __transition__. Идея состоит в том, чтобы проверить, существует ли __transition__, и если да, дождитесь, пока он не начнет новый (суб) переход.

Для этого он помогает продлить прототип выбора с помощью соответствующей функции:

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

Обратите внимание, что это крайне хаки и работает только в том случае, если в выборе есть ровно один элемент с одним переходом. Вы должны понять эту идею.

Теперь мы можем использовать эту функцию, чтобы определить, выполняется ли переход.

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

К сожалению, __transition__ не позволяет вам восстановить объект перехода, то есть следующее не будет работать.

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

Итак, чтобы смоделировать субпереход, который начинается после завершения текущей версии, используйте setTimeout, чтобы проверить, работает ли что-то, и как только ничего нет, начните новый переход:

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

Вы можете уменьшить интервал между проверками (здесь 100 мс), чтобы создать лучшее впечатление о переходе, который сразу же следует за предыдущим.

Заполните пример здесь. Обратите внимание, что почти во всех случаях гораздо проще и лучше сохранять ссылку на объект перехода где-то и использовать это. Этот пример действительно служит лишь хакерским доказательством концепции.