Как я анимировал свой визуализатор алгоритма сортировки
Недавно я сделал то, что давно хотел сделать, и, честно говоря, это застревало у меня в голове последние два с лишним года, но до недавнего времени мне так и не удалось это реализовать.
Публикация исходного содержимого DevCanvas (онлайн-редактор HTML/CSS/JS), над которым я сейчас работаю, дала мне мотивацию поэкспериментировать с созданием визуализатора алгоритмов.
Кроме того, это прекрасное время для создания веб-приложений, и многие вещи, которые раньше выполнялись вручную, теперь изначально принимаются браузерами. Это подводит меня к сути этой статьи — View Transitions API.
View-transitions-api некоторое время находился в разработке и все еще находится на экспериментальной стадии, но шумиха вокруг него начала расти только в последнее время, что также привлекло к нему мое внимание.
Что такое View Transitions API
API был введен для решения проблемы перехода между состояниями. Выполнение этих переходов никогда не было простым, и часто требовалось много работы и многословия, просто чтобы сделать взаимодействие с пользователем немного приятнее.
Настройка этого самостоятельно отнимает много нашего драгоценного времени и часто не идеальна и в некоторых отношениях имеет серьезные недостатки. Хотя у Svelte (моего самого любимого фреймворка) есть решение для этой проблемы, переходы представлений, когда они будут полностью готовы и поддерживаются, значительно упростят задачу.
Тем не менее, мы собираемся углубиться и посмотреть, как это работает и как мне удалось добиться волшебства плавного перехода в моем визуализаторе алгоритма сортировки.
Как это работает
Говорят, что view-transition-api фиксирует состояние DOM
до и после и плавно выполняет соответствующий переход.
Как я создавал визуализатор
Разбивка этапов выглядит следующим образом:
- Создайте какие-то столбцы с массивом
- При каждом завершенном действии алгоритма сортировки заменяйте старые столбцы новым массивом.
Это весь план, и с моими небольшими знаниями в JavaScript и CSS я не знаю, как смогу это анимировать. К счастью, я принадлежу к более удачливому поколению, и у меня есть view-transitions-api.
Один очень интересный факт заключается в том, что весь переход занимает не более двух строк, а может, и трех, если честно.
В создании визуализатора участвуют две функции:
- Обновление DOM
Эта функция принимает массив, который является глобальными данными, создает столбцы и добавляет их в эту позицию.
function renderChart() {
chartContainer.innerHTML = '';
const maxValue = Math.max(...data);
data.forEach((value) => {
const bar = document.createElement('div');
bar.classList.add('bar');
bar.style.setProperty('--tag', `bar-${value}`);
const percentageHeight = (value / maxValue) * 100;
bar.style.height = `${percentageHeight}%`;
bar.textContent = value;
chartContainer.appendChild(bar);
});
}
Один из шагов перехода находится в этой функции bar.style.setProperty('--tag',bar-${value})
, которая устанавливает собственный тег для каждого из столбцов. используя панель-КАКОЕ-ЧИСЛО-Есть. Это значение должно быть уникальным и будет идентификатором, сообщающим нашему браузеру, что куда переместилось или как выполнять математические действия.
- Алгоритм сортировки
async function bubbleSortWithDelay(arr) {
const len = arr.length;
let swapped;
async function sort() {
do {
swapped = false;
for (let i = 0; i < len - 1; i++) {
if (arr[i] > arr[i + 1]) {
const temp = arr[i];
arr[i] = arr[i + 1];
arr[i + 1] = temp;
swapped = true;
console.log(arr); // Log array after each swap
const transition = document.startViewTransition(() => renderChart());
await delay(speed); // Delay in milliseconds (adjust as needed)
}
}
} while (swapped);
}
return sort().then(() => arr);
}
Я выбираю здесь пузырьковую сортировку просто потому, что так легче увидеть, что происходит.
Погружаясь в эту функцию, вы впервые столкнетесь с дополнительным шагом, добавляющим задержку, которая представляет собой функцию setTimeout
. Она помогает создать интервал между циклами и, следовательно, используется для увеличения или уменьшения скорости визуализатора.
Также в этой функции вызывается const transition = document.startViewTransition(() => renderChart())
.
startViewTransition
мгновенно фиксирует текущее состояние нашего DOM
, а функция, предшествующая renderChart()
, обновляет DOM
.
Это суммирует всю логику визуализатора, а также переход.
Если остановиться здесь, мы получим плавное затухание между предыдущим и последующим состояниями, и это будет выглядеть очень странно. Нам нужен отдельный переход тактов, а не весь материал целиком.
Итак, мы можем исправить это, добавив view-transition-name
, оно сообщит браузеру об этой отдельной панели и автоматически анимирует ее новую позицию, если она изменится.
.bar {
view-transition-name: var(--tag);
}
И вы можете видеть, что я использую тег, который мы добавили к полосам ранее.
Итак, теперь, когда DOM обновляется, API переходов представления видит что-то вроде этого: скажем, --bar-23
находится в первой позиции в массиве, когда цикл завершается, новая позиция перемещается на 4-ю, API может Плавно рассчитайте и творите за нас волшебство движений.
Вот окончательный результат работы визуализатора. Опять же, если вы используете неподдерживаемый браузер, например Safari и Firefox, это не сработает.
Просмотр переходов в документации MDN: Просмотр API перехода