2016-12-31 4 views
4

Я пытаюсь играть с переходами d3 - мне нужно делать и переводить, и вращать. У меня есть оригинальные координаты:d3 переводить поворот порядка при переходе

let data = [ 
    {x: 100, y: 100, rotation: 45}, 
]; 

и 2 прямоугольников. Один делает перевод сначала, второй выполняет ротацию .

Это в результате преобразования после рисования прямоугольников:

transform="rotate(45 115 105) translate(100, 100)" 
transform="translate(100, 100) rotate(45 115 105)" 

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

Затем я изменяю данные:

data[0].x += 30; 
data[0].y += 20; 
data[0].rotation += 45; 

, и я бы ожидать, чтобы получить какой-то переход в конечном итоге с этой трансформации:

transform="rotate(90 145 125) translate(130, 120)" 
transform="translate(130, 120) rotate(90 145 125)" 

но то, что я действительно получаю это:

transform="translate(150, 110) rotate(90)" 
transform="translate(400, 100) rotate(90)" 
  • Извещение об изменении порядка перевода для первого прямоугольника.
  • он также удаляет центр вращения из поворотного преобразования (он как-то вычисляет его во время перехода?)
  • как он получит результирующие числа?

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

Вот простой пример: https://jsfiddle.net/pp6npw4g/2 (нажмите, чтобы начать движение перехода)

+0

Не связано с вашей реальной проблемой, но просто для краткости, ясности и для получения любого возможного источника ошибки: в вашем JSFiddle вы выполняете '.attr ('transform', (d) => transformFunction (d)); ', который просто переносит вызов' transformFunction() 'в еще одну анонимную функцию. Это в основном эквивалентно '.attr ('transform', transformFunction),' просто передавая ссылку на функцию. – altocumulus

+0

Я знаю, это просто пример. В реальном приложении я делаю больше вещей, а не только один вызов функции. Но вы правы, в этом примере это может быть упрощено. – Klinki

+0

Ничего! Просто многие люди путаются по этому поводу. Престижность для упрощения и предоставления урезанного примера вместо простого сброса всего кода! – altocumulus

ответ

2

Это ожидаемое поведение для стандартной интерполяции D3 о значении атрибута transform. Атрибут transform, как известно, трудно переходить, поскольку его значение может содержать сложный список определений преобразования, который может появляться в любом порядке и может появляться несколько раз в одном списке. Например:

transform="translate(100) rotate(30, 100, 100) scale(2.5) translate(-10, -50) skewX(20)" 

Чтобы иметь возможность перехода между этими значениями, функция transition.attr() использует d3.interpolateTransformSvg(a, b) когда дело доходит до интерполяции значений transform атрибутов. Это делает следующее:

  1. В функции внутренней parseSvg() модуль d3-интерполировать список преобразования определений вареных вниз по телефону .consolidate() интерфейса SVGTransformList.

  2. Использование собственной функции decompose() это консолидированы преобразование затем разлагают в его значений перевести, вращать, перекос и масштаб.

Я описал этот процесс разложения списка преобразования в моем answer к "Replacing d3.transform in D3 v4".

В процессе перехода интерполятор, возвращаемый d3.interpolateTransformSvg(a, b) будет интерполировать между соответствующими значениями a и b для (1) translate, (2) rotate, (3) skewX и (4) scale именно в этом order.

Это дает вам консолидированные значения, которые, поначалу, могут показаться неожиданными. Кроме того, он объясняет, почему порядок преобразований был изменен в результате перехода. Чтобы обойти это и реализовать пользовательский переход, вам нужно будет предоставить настраиваемую функцию твинов, которая может быть назначена вызовом transition.attrTween(). Однако реализация этой функции во многом зависит от ваших потребностей и выходит за рамки этого ответа.

+0

Спасибо за объяснение! Я постараюсь играть с функцией tween. – Klinki