От автора: для клиентского проекта нам поручили не что иное, как сделать прогресс бар, причем радиальный. Раньше мы использовали целые Canvas графические библиотеки (156k / 44k gzip), но это казалось излишним. Я посмотрел проект Lottie от Airbnb, в котором экспортируется анимация After Effects, как JSON. Это классно для сложной анимации, но зависимости для одной этой микро-анимации оказались слишком объемными (248k / 56k gzip).
Как обычно, я сам попробовал внести свои коррективы и применить пользовательский SVG с CSS-анимацией и небольшим количеством JavaScript (~ 223b gzip). Я остался доволен результатом.
Это работает в IE9 +, Edge, Chrome, Firefox и Safari. Анимация (фактически, переход) является прогрессивным улучшением, поэтому в браузерах, которые не поддерживают CSS-переходы в SVG, будет отображаться статическая графика. Если вы хотите узнать, как я это сделал, продолжайте читать …
Как это работает: клонирование, измерение и переход
Я приведу подробный обзор, как это работает. Под капотом мы используем ту же технологию для анимированных линий, которая приводила в действие эпическую анимацию Xbox One Review от Polygon. Мне она нравится тем, что все выглядит сложным, но на самом деле здесь применяется один transition для одного свойства stroke-dashoffset одного <path>.
Но прежде чем мы перейдем к сложной части и анимируем дугу, давайте начнем с простого — анимируем линейный прогресс-бар, чтобы увидеть, как все это работает …
Пройдитесь на вкладкам HTML / CSS / JS в блоке CodePen. Вероятно, на просмотр кода у вас уйдет около минуты. А вот, чтобы понять этот код нужно немного больше времени. Рабочий процесс HTML / CSS выглядит следующим образом:
Создаем SVG с одним path. Это будет «пустой» фон.
Запускаем SVG через SVGOMG.
Копируем и вставляем путь и задаем для клона class=»meter».
Изменяем цвет stroke клона.
Применяем для meter следующее transition: stroke-dashoffset 850ms.
Жестко задаем для stroke-dasharray и stroke-dashoffset длину meter.
Вы можете динамически устанавливать свойства stroke-dash*, но чтобы предотвратить вероятность сбоя анимации, стоит задать его жестко. Чтобы получить длину пути, введите в консоли следующее:
document.querySelector('path').getTotalLength();
Далее я указываю значение meter, используя в SVG атрибут data-value. Последний SVG должен выглядеть примерно так:
<svg width="200" height="20" data-value="40"> <style> .bg, .meter { fill: none; stroke-width: 20px; stroke-miterlimit: round; } .meter { transition: stroke-dashoffset 850ms ease-in-out; stroke-dasharray: 200; stroke-dashoffset: 200; } </style> <path class="bg" stroke="#ccc" d="M0 10, 200 10"></path> <path class="meter" stroke="#09c" d="M0 10, 200 10"> </path> </svg>
SVGOMG может преобразовать некоторые стили в свойства. В любом случае это полезно. Затем на стороне JavaScript мы выполняем следующие 4 действия:
Измеряем длину пути
Получаем переданное значение из data-value
Вычисляем новое смещение (в процентах от оригинала)
Устанавливаем новый stroke-dashoffset
document.querySelectorAll('path.meter').forEach(path => { let length = path.getTotalLength(); let maxValue = 100; let value = parseInt(path.parentNode.getAttribute('data-value')); let to = length * ((maxValue - value) / 100); // Запускаем Layout для Safari // https://jakearchibald.com/2013/animated-line-drawing-svg/ path.getBoundingClientRect(); path.style.strokeDashoffset = Math.max(0, to); });
Теперь наши meter должны заполняться до нужной величины в соответствии со степенью загрузки страницы. Для старых браузеров вам понадобится полифилл 200b NodeList forEach. Одним из улучшений, которые вы можете сделать, является динамическое определение maxValue в таком атрибуте данных, как value. В качестве еще одного улучшения для увеличения доступности вы можете добавить некоторый описательный текст в элементе title.
Радиальное решение
Теперь, когда мы знаем, как анимировать прямой путь, давайте сделаем это для радиального пути применив те же приемы клонирования, измерения и перехода.
Эффект настолько прост, что вы можете анимировать любой нужный путь.
Мне нравится то, что получилось. Всегда полезно сохранить на будущее пару интересных решений в архиве кодов. Всякий раз, когда мне нужно что-то более интересное, чем элемент progress, я могу использовать их. Если вам нравятся этот прием из «6 строк JavaScript», обязательно добавьте страницу в «Избранное», поделитесь ссылкой и подпишитесь на обновления в своем RSS-ридере.
Источник: https://daverupert.com/
Редакция: Команда webformyself.