D3 Transitions
помогают графику плавно переходить между различными состояниями и создавать анимацию. В этой статье показано, как добавлять Transitions
, периоды перехода
, перекрывающиеся переходы
, функции затухания
и цепные переходы
к выборке элементов (Selection)
.
Например, массив данных подключается к SVG-circle
, и при нажатии кнопки update
данные случайным образом изменяются, что заставляет circle
перемещаться на новые позиции. Сначала посмотрим на эффект без Transitions
:
! transition1
Если мы добавим переходы к кругам, они будут плавно перемещаться на свои новые позиции:
! transition2
Кроме того, входящие круги (ново созданные circle
) и выходящие круги (круги, которые нужно удалить) могут быть анимированы различными способами. В этом примере входящие
круги появляются с эффектом fade In (появление)
, а выходящие
круги исчезают с эффектом drop Down (опускание)
:
! transition3
Использование D3 для создания базового перехода (basic transition)
очень просто. Сначала подключаем несколько случайных данных к элементам circle
:
let data = [];
function updateData() {
data = [];
for(let i=0; i<5; i++) {
data.push(Math.random() * 800);
}
}
function update() {
d3.select('svg')
.selectAll('circle')
.data(data)
.join('circle')
.attr('cy', 50)
.attr('r', 40)
.attr('cx', function(d) {
return d;
});
}
function updateAll() {
updateData();
update();
}
updateAll(); // При нажатии кнопки
При нажатии кнопки данные изменяются (в основном координата x
), и круги прыгают на новые позиции:
Затем, для добавления стандартного эффекта перехода достаточно добавить
.transition()
перед .attr()
:
function update() {
d3.select('svg')
.selectAll('circle')
.data(data)
.join('circle')
.attr('cy', 50)
.attr('r', 40)
.transition()
.attr('cx', function(d) {
return d;
});
}
Метод
.transition
возвращает объектtransition selection
. Он похож на обычныйD3 Selection
, за исключением того, что методы.attr
и.style
анимируют атрибуты и стили. В объектеtransition selection
также есть метод.tween
. После вызова метода.transition
последующие вызовы методов.attr
и.style
анимируют атрибуты и стили. Например, давайте случайным образом настроим некоторые атрибуты и стили для каждого круга:function random(x) {return Math.floor(Math.random() * x);}// Генерация случайного числа и округление function updateData() { data = []; for(let i=0; i < 5; i++) { data.push({ x: random(750), r: random(50), fill: d3.rgb(random(255), random(255), random(255)), opacity: Math.random() }); } }В функции
update
мы обновляем атрибуты и стили кругов после вызова метода.transition
:function update() { d3.select('svg') .selectAll('circle') .data(data) .join('circle') .attr('cy', 50) .transition() .attr('cx', function(d) { return d.x; }) .attr('r', function(d) { return d.r; }) .attr('fill', function(d) { return d.fill; }) .attr('opacity', function(d) { return d.opacity; }); } ``````markdown
attr('r', function(d) { return d.r; }) .style('opacity', function(d) { return d.opacity; }) .style('fill', function(d) { return d.fill; }); }
Теперь, когда данные обновляются, позиция, радиус, прозрачность и цвет каждого круга изменяются:

> https://codepen.io/wantnocode/pen/rNdgNzY?editors=1111
## Входящие и исходящие элементы
Можно определить специальные `transition` для **входящих** и **исходящих** элементов. (Входящие элементы — это новые элементы, а исходящие элементы — те, которые будут удалены.)
Например, **входящие круги** (новые `circle`) и **исходящие круги** (круги, которые будут удалены) могут быть анимированы различными способами: `входящие` — `появление`, `исходящие` — `исчезновение`.

Чтобы определить `transition` для входящих и исходящих элементов, необходимо передать **три функции** методу `.join`.
.join( function(enter) { ... }, function(update) { ... }, function(exit) { ... } )
Первый, второй и третий функции отвечают за поведение, которое является **входом** (enter), **обновлением** (update) и **выходом** (exit).
### Входящие элементы
Функция `enter` принимает параметр `Selection` для каждого элемента.
Мы можем установить стили и атрибуты входящих элементов, что позволяет инициализировать эффект элементов до того, как будет запущен любой `transition`.
``` Давайте инициализируем `cy`, `cx`, `r` и `opacity`:
. join( function(enter) { return enter . append('circle') . attr('cy', 50) . attr('cx', function(d) { return d; }) . attr('r', 40) . style('opacity', 0); }, function(update) { return update; }, function(exit) { return exit. remove(); } )
Инициализируем начальные координаты x и y входящих кругов, чтобы круги появлялись в правильных местах (а не скользили с начала координат).
Инициализируем начальный радиус входящих кругов, чтобы круги появлялись с радиусом 40.
Наконец, прозрачность входящих кругов инициализируется значением 0, чтобы входящие круги плавно появлялись (позже мы установим окончательную прозрачность).
### Выходящие элементы
Функция `exit` удаляет элементы из выборки выхода:
. join( . . . function(exit) { return exit. remove(); } )
> Примечание: Если `. remove` не вызывается для выборки выхода, элементы останутся на странице.
`. transition` может добавить переход к выходящим элементам, вызывая `exit selection`. Например, чтобы добавить эффект `down` для существующих элементов, удаляющихся с страницы, можно установить атрибут `cy` большим значением:
. join( function(enter) { . . . }, function(update) { . . . }, function(exit) { return exit . transition() . attr('cy', 500) . remove(); // Удаляем элементы } )
Метод `. remove` `transition selection` удаляет элементы выборки после завершения перехода.
### Обновление элементов `Обновление` можно представить как конечный результат входящих элементов, а также начальный результат перехода выходящих элементов.
Например, давайте добавим `.transition` для конечного представления входящих элементов (входящих элементов): это атрибуты `opacity` и `cx`:
d3.select('svg') .selectAll('circle') .data(data) .join( function(enter) { . . . }, function(update) { . . . }, function(exit) { . . . } ) .transition() .attr('cx', function(d) { return d; }) .style('opacity', 0.75);
- Когда данные изменяются, `circle` плавно переходят на новое положение (`.attr('cx')`)
- При создании `circle` они плавно появляются
**Смотрите полный пример ниже:**
- `circle` плавно появляются
- `circle` плавно переходят на новое положение
- При выходе `circle` они плавно исчезают с экрана
function update() { d3.select('svg') .selectAll('circle') .data(data) .join( function(enter) { return enter .append('circle') .attr('cy', 50) .attr('cx', function(d) { return d; }) .attr('r', 40) .style("fill", "blue") .style('opacity', 0.1); }, function(update) { return update; }, function(exit) { return exit .transition() .duration(1000) // Продолжительность перехода .attr('cy', 500) .remove(); } ) .transition() .duration(1000) // Продолжительность перехода .attr('cx', function(d) { return d; }) .style('opacity', 0.75); }

## Продолжительность и задержка
Вы можете установить продолжительность перехода, вызвав `.duration` перед методом `.transition`. Метод `.duration` принимает один параметр, который указывает продолжительность в миллисекундах:
d3.select('svg') .selectAll('circle') .data(data) .join( // . . . ) .transition() .duration(2000) // Продолжительность перехода .attr('cx', function(d) { return d; }) .style('opacity', 0.75);
Например, установим продолжительность перехода для входящих элементов в 2000 миллисекунд:
! [transition5](https://user-images.githubusercontent.com/32726183/199651966-61fd2537-756b-4b87-ad00-762560c4e39d.gif)
> https://codepen.io/wantnocode/pen/RwMmNLG
Также можно указать задержку перед началом перехода с помощью `.delay`:
. . . .transition() .delay(2000) .attr('cx', function(d) { return d; });
Задержка обычно используется для установки различных значений для каждого элемента в `Selection`. Например, задержка для каждого элемента может быть установлена по индексу `.delay * i` : (для достижения эффекта постепенного появления)
d3.select('svg') .selectAll('circle') .data(data) .join('circle') .attr('cy', 50) .attr('r', 20) .transition() .delay(function(d, i) { return i * 100; }) .attr('cx', function(d) { return d; });
> https://codepen.io/wantnocode/pen/wvmbBjp?editors=1111
## Функции затухания
**Функции затухания** определяют изменения скорости элемента во время перехода и могут быть использованы в D3.D3 имеет множество встроенных функций затухания ([подробнее о функциях затухания можно посмотреть здесь](https://github.com/d3/d3-ease#ease_ease)):
["easeBack","easeBackIn","easeBackInOut","easeBackOut","easeBounce","easeBounceIn","easeBounceInOut","easeBounceOut","easeCircle","easeCircleIn","easeCircleInOut","easeCircleOut","easeCubic","easeCubicIn","easeCubicInOut","easeCubicOut","easeElastic","easeElasticIn","easeElasticInOut","easeElasticOut","easeExp","easeExpIn","easeExpInOut","easeExpOut","easeLinear","easePoly","easePolyIn","easePolyInOut","easePolyOut","easeQuad","easeQuadIn","easeQuadInOut","easeQuadOut","easeSin","easeSinIn","easeSinInOut","easeSinOut"]
! [transition7](https://user-images.githubusercontent.com/32726183/199652015-ff609cb1-4f3c-453a-9ba2-5d5aa3114fac.gif)
> https://codepen.io/wantnocode/pen/GRxaJKO?editors=1111
> Обычно, "in" означает начало движения, а "out" — его конец. Таким образом, `easeBounceOut` означает, что элемент будет **отскакивать в конце перехода.** `easeBounceInOut` заставляет элемент **отскакивать как в начале, так и в конце перехода.**
> Обычно лучше использовать функции затухания, когда элемент начинает быстро двигаться и затем замедляется. Например, `easeCubicOut` — часто используемая функция затухания, при которой элемент сначала быстро движется, а затем замедляется. По умолчанию D3 использует функцию затухания `easeCubic`, которая эквивалентна `easeCubicInOut`. Это приводит к тому, что элемент начинает медленно, ускоряется, а затем замедляется к концу.
## Цепные переходы
`transition` можно объединить, добавляя несколько вызовов (то есть использовать цепную конструкцию). Каждый `transition` будет выполнен.(**Порядок выполнения: когда первый переход завершается, начинается второй, и так далее.**)
Например, давайте соединим два `transition` для использования. Первый устанавливает атрибут `cx`, а второй — атрибут `r` (используя `easeElastic`):
d3.select('svg') .selectAll('circle') .data(data) .join('circle') .attr('cy', 50) .style("fill", "blue") .transition() .attr('cx', function(d) { return d.x; }) .transition() .duration(1000) .ease(d3.easeElastic) .attr('r', function(d) { return d.r; });
Когда диаграмма обновляется, `circle` перемещается в новые координаты, а затем изменяется значение `r`:

> https://codepen.io/wantnocode/pen/wvmbazY?editors=1112
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Опубликовать ( 0 )