D3 arc и SVG 2d на 3d изменение перспективы - PullRequest
0 голосов
/ 02 февраля 2019

У меня есть SVG с группой независимых дуг, которые перемещаются вокруг общего источника.По событию пользователя эти дуги могут изменять как свои радиусы, так и начальный / конечный углы.В другом пользовательском событии пользователь может изменить вид с 2d на поддельный 3d (орфографический?) С помощью следующего преобразования CSS, как описано здесь :

translate(0px, ${t*5 - i*t*40}px)
rotateX(${t*60}deg)
rotateZ(${t*-30}deg)
scale(1.0)

t - логический флаг, указывающий, является ли перспективапредставление включено или выключено, если флаг = 0, тогда фактическое преобразование не выполняется.

Мой код, иллюстрирующий пример, можно посмотреть здесь: https://codepen.io/stopyransky/pen/MZPbjg

После нажатия кнопки для запуска перспективывид, что он изменяется правильно, но дуговые переходы (радиусы / угол) теперь испорчены.

Мой вопрос, как исправить, чтобы переходы дуг оставались правильными?Я предполагаю, что мне нужно изменить функции, которые изменяют способ построения дуги в tweenAngles и tweenRadii, но я понятия не имею, какими должны быть эти переходы.Я пытался отменить переходы, когда флаг равен 0, но это не помогает.

1 Ответ

0 голосов
/ 20 июня 2019

После обсуждения на Анимация на работе, свободный канал и помощь пользователя канала 'mamboleoo' Я могу дать ответ на свой вопрос.

Первая проблема заключалась в использовании node.style.transition = "ease 1s all"; внутри togglePerspective функция.Без этого пути правильно анимируются в трехмерном виде, но мы пропускаем переход между двухмерным и трехмерным видами при нажатии кнопки.

Чтобы исправить это, нам нужно создать собственный d3.styleTween в togglePerspective:

function togglePerspective() {
  perspective = !perspective;

  d3.selectAll('path').each((d, i, n) => {
    const node = n[i];
    // OLD
    // node.style.transition = "ease 1s all";
    // node.style.transform = perspectiveTween(perspective, i);

    node.style.transformOrigin = "20% 20%";

    // NEW LINES
    const tr = d3.transition().duration(3000);

    d3.select(node).transition(tr)
      .styleTween('transform', () => {
        return function(time) { // interpolation fn (time = 0...1)
          return perspectiveTween(perspective, i, time);
        }
      }); 
  });
}

где в функции perspectiveTween мы параметризуем ранее фиксированные значения преобразования:

function perspectiveTween(perspective, i, time) {
  const T = perspective ? time : (1-time);
  const xRotation = (60 * T);
  const yRotation = (-30 * T);

  const yTranslation = (T*5) - i*(T * 10);

  return `
    translate(0px, ${yTranslation}px)
    rotateX(${xRotation}deg)
    rotateZ(${yRotation}deg)
    scale(1.0)`
};

рабочий пример: https://codepen.io/stopyransky/pen/NZdawR

...