Как добавить условные переходы? - PullRequest
2 голосов
/ 24 февраля 2020

Этот вопрос касается переходов с d3. js, например, изменение атрибута x прямоугольника.

Если вы хотите, чтобы изменение произошло немедленно, вы можете установить delay = duration = 0 как в

svg.selectAll("rect")
   .transition()
   .delay(delay)
   .duration(duration)
   .attr("x", 0)

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

if (delay == 0 && duration == 0) {
    svg.selectAll("rect")
        .attr("x", 0)
} else {
    svg.selectAll("rect")
        .transition()
        .delay(delay)
        .duration(duration)
        .attr("x", 0)
}

, но менее избыточный и более компактный, как-то как x = condition ? 0 : 1?

1 Ответ

6 голосов
/ 24 февраля 2020

Это очень странная ситуация, и я не могу думать о случае использования, где это было бы полезно. Тем не менее, вот одно из многих возможных решений: расширить прототип выбора D3.

В моем подходе мы расширим прототип, чтобы он возвращал точно такой же выбор в случае как delay, так и duration равны нулю или возвращают переход выбор, основанный на текущем выборе, если они не равны нулю:

d3.selection.prototype.conditionalTransition =
  function(cond1, cond2) {
    return cond1 && cond2 ? this.transition().duration(duration).delay(delay) : this;
  };

Затем вы просто продолжаете цепочку методов attr():

d3.selectAll("rect")
  .conditionalTransition(delay, duration)
  .attr("x", 200);

Наконец, обратите внимание на тот факт, что регулярные выборки и переходы имеют разные методы с одинаковыми именами, например selection.on() и transition.on().

Вот первая демонстрация , Все тезисы в x = 10. Выбор превращается в переход выбора:

d3.selection.prototype.conditionalTransition =
  function(cond1, cond2) {
    return cond1 && cond2 ? this.transition().duration(duration).delay(delay) : this;
  };

const rect = d3.selectAll("rect");

const delay = 100,
  duration = 1000;

rect.conditionalTransition(delay, duration)
  .attr("x", 200)

function transitioning(sel) {
  return sel.transition()
    .delay(delay)
    .duration(duration);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<svg>
 <rect x="10" y="10" width="50" height="20" fill="teal"></rect>
 <rect x="10" y="40" width="50" height="20" fill="teal"></rect>
 <rect x="10" y="70" width="50" height="20" fill="teal"></rect>
 <rect x="10" y="100" width="50" height="20" fill="teal"></rect>
</svg>

А здесь один и тот же код, где delay и duration равны нулю. Как вы можете видеть, прямоугольники уже находятся в конечной позиции, переход отсутствует:

d3.selection.prototype.conditionalTransition =
  function(cond1, cond2) {
    return cond1 && cond2 ? this.transition().duration(duration).delay(delay) : this;
  };

const rect = d3.selectAll("rect");

const delay = 0,
  duration = 0;

rect.conditionalTransition(delay, duration)
  .attr("x", 200)

function transitioning(sel) {
  return sel.transition()
    .delay(delay)
    .duration(duration);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<svg>
 <rect x="10" y="10" width="50" height="20" fill="teal"></rect>
 <rect x="10" y="40" width="50" height="20" fill="teal"></rect>
 <rect x="10" y="70" width="50" height="20" fill="teal"></rect>
 <rect x="10" y="100" width="50" height="20" fill="teal"></rect>
</svg>
...