Как снизить нагрузку на ЦП при использовании анимации на сайте?
помогите пожалуйста с такой проблемой.
На сайте есть анимация, она сделана в AE и преобразована плагином bodymovin в json файл (+ папка с png).
Подключил на сайт по туториалу, в JS вообще не силен, открываю и вижу нагрузку на ЦП 50-70%.
Файл json весит 800 кб!, не пойму кто виноват, может я как то не правильно подключил и использую этот скрипт?
Я выложил пример на свой хостинг.
http://animate.d58147.hostru06.fornex.host/
bodymovin.loadAnimation({
container: document.getElementById('animate'),
render: 'svg',
loop: true,
autoplay: true,
path: 'js/virtualization.json'});
Ответы (3 шт):
Вряд ли кто-то возьмется разбирать и оптимизировать гигантский код после обработки плагинами, но можно попытаться сделать аналогичную анимацию простыми анимациями CSS и SVG/ Анимировать все элементы, как в примере очень трудоемко, это получится уже работа под заказ, а не ответ, но некоторые моменты можно показать, как это делается. Остальные анимации автор вопроса, по образцу, может попытаться сделать сам.
Подготовка растровой картинки к анимации
Это самый трудоемкий и ответственный момент.
Понадобятся некоторые минимальные навыки работы с векторным и растровым редакторами.
Совсем необязательно сохранять картинку в векторном редакторе в формате *.svg, так как код получается огромным и запутанным, в котором довольно трудно найти фрагменты для анимации. Можно нарисовать в векторном редакторе и сохранить изображение в формате *.png
Получается, что проще взять растровую картинку и дорисовать поверх неё, например линии, которые будут анимироваться.
Ниже показана техника, по шагам, как это делается.
Ещё преимущества этого метода заключаются в том, что приложение будет адаптивным, верстка не развалится при любом дисплее гаджета и в любой момент можно, что-то поменять.
Шаг 1
Берем растровую картинку, я снял скриншот вашей анимации. Размеры картинки составляют
568 х 532px Вот эти размеры я добавляю в заготовку svg файла.
<svg version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="568" height="538" viewBox="0 0 568 538" preserveAspectRatio="xMinYMin meet">
<image xlink:href="https://i.stack.imgur.com/RjYfh.png" width="100%" height="100%" />
</svg>
Шаг 2
Загружаем этот файл в векторный редактор, например в Inkscape и поверх линий, которые будут анимироваться, наносим узловые точки с помощью инструмента Рисовать кривые Безье
На рисунке красная стрелка.
Сохраняем файл в формате *.svg
Шаг 3
Необходимо очистить от служебной информации Inkscape, сохраненный файл.
Я пользуюсь: SVG_EDITOR
У него две вкладки , в общем-то всё интуитивно понятно
Input | Optimise
На картинке 5 path, которые будем анимировать
.trace{
fill:none;
stroke:#917FDE;
stroke-width:3;
stroke-dasharray: 5,2;
}
#path5 {
stroke-dasharray:331;
}
<svg version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="568" height="538" viewBox="0 0 568 538" preserveAspectRatio="xMinYMin meet">
<image xlink:href="https://i.stack.imgur.com/RjYfh.png" width="100%" height="100%" />
<path class="trace" class="path1" d="m353.9 285.2 33.6-19.7M281.7 344.2l0.3 10.9" />
<path class="trace" class="path2" d="m281.7 344.2 0.3 10.9c0 0 0.1 2.3 0.1 3.6 0 1 0.9 1.1 2.5 2 6.8 3.9 25.2 14 33.7 20.1 0.7 0.5 0.1 7.4 0.3 12 0 1.4-0.3 3.5 0.9 4.3 3.6 2.6 6.3 3.6 10.3 6 8.1 4.8 16.8 9.4 22.9 13.2 4.7 2.9 7.7 4.8 7.7 4.8" />
<path class="trace" class="path3" d="m156.4 383 19.9-11.4-0.6-14 34.2-20.2-0.3-67.5 4.6-2.8" />
<path class="trace" class="path4" d="M196.3 275.6 148.5 246.5" />
<path class="trace" id="path5" d="M414.3 335.1 276.4 414.3c0 0-4.4 2.7-6.8 2.8-2.9 0.2-8.5-2.3-8.5-2.3L127.7 335.1" >
</path>
</svg>
Файл, необходимый для анимации, получен
Анимация CSS
Анимацию рисование линий будем реализовывать с помощью изменения stroke-dashoffset от максимального значения равного длине линии 331px до нуля. Реализуя тем самым анимацию появления линии от нуля до полной длины линии.
#1.Рисование линии вперед-назад:
- Если не нужна анимация вперед назад, уберите
alternate - Для анимации без повторений удалите
infinite
.trace{
fill:none;
stroke:#917FDE;
stroke-width:4;
}
#path1, #path2, #path3, #path4, #path5 {
stroke-dasharray:331;
stroke-dashoffset:331;
animation: draw 3s linear infinite alternate ;
}
@keyframes draw {
100% { stroke-dashoffset: 0;}
}
<svg version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="568" height="538" viewBox="0 0 568 538" preserveAspectRatio="xMinYMin meet">
<image xlink:href="https://i.stack.imgur.com/n9Btd.jpg" width="100%" height="100%" />
<path class="trace" id="path1" d="m353.9 285.2 33.6-19.7M281.7 344.2l0.3 10.9" />
<path class="trace" id="path2" d="m281.7 344.2 0.3 10.9c0 0 0.1 2.3 0.1 3.6 0 1 0.9 1.1 2.5 2 6.8 3.9 25.2 14 33.7 20.1 0.7 0.5 0.1 7.4 0.3 12 0 1.4-0.3 3.5 0.9 4.3 3.6 2.6 6.3 3.6 10.3 6 8.1 4.8 16.8 9.4 22.9 13.2 4.7 2.9 7.7 4.8 7.7 4.8" />
<path class="trace" id="path3" d="m156.4 383 19.9-11.4-0.6-14 34.2-20.2-0.3-67.5 4.6-2.8" />
<path class="trace" id="path4" d="M196.3 275.6 148.5 246.5" />
<path class="trace" id="path5" d="M414.3 335.1 276.4 414.3c0 0-4.4 2.7-6.8 2.8-2.9 0.2-8.5-2.3-8.5-2.3L127.7 335.1" >
</path>
</svg>
#2. Рисование линии вперед-назад: второй вариант
Так как длина линий сильно отличается сделаем две анимации: одна для длинной линии
#path5 {
stroke-dasharray:331;
stroke-dashoffset:331;
animation: drawLong 1.5s linear 3s forwards ;
}
Остальные анимация для более коротких линий
.trace{
fill:none;
stroke:#917FDE;
stroke-width:4;
}
#path1, #path2, #path3, #path4 {
stroke-dasharray:150;
stroke-dashoffset:150;
animation: draw 4s linear infinite alternate ;
}
@keyframes draw {
100% { stroke-dashoffset: 0;}
}
#path5 {
stroke-dasharray:331;
stroke-dashoffset:331;
animation: drawLong 1.5s linear 3s forwards ;
}
@keyframes drawLong {
100% { stroke-dashoffset: 0;}
}
<svg version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="568" height="538" viewBox="0 0 568 538" preserveAspectRatio="xMinYMin meet">
<image xlink:href="https://i.stack.imgur.com/n9Btd.jpg" width="100%" height="100%" />
<path class="trace" id="path1" d="m353.9 285.2 33.6-19.7M281.7 344.2l0.3 10.9" />
<path class="trace" id="path2" d="m281.7 344.2 0.3 10.9c0 0 0.1 2.3 0.1 3.6 0 1 0.9 1.1 2.5 2 6.8 3.9 25.2 14 33.7 20.1 0.7 0.5 0.1 7.4 0.3 12 0 1.4-0.3 3.5 0.9 4.3 3.6 2.6 6.3 3.6 10.3 6 8.1 4.8 16.8 9.4 22.9 13.2 4.7 2.9 7.7 4.8 7.7 4.8" />
<path class="trace" id="path3" d="m156.4 383 19.9-11.4-0.6-14 34.2-20.2-0.3-67.5 4.6-2.8" />
<path class="trace" id="path4" d="M196.3 275.6 148.5 246.5" />
<path class="trace" id="path5" d="M414.3 335.1 276.4 414.3c0 0-4.4 2.7-6.8 2.8-2.9 0.2-8.5-2.3-8.5-2.3L127.7 335.1" >
</path>
</svg>
Анимацию движения шарика вдоль линии лучше делать в SVG, так как движение элементов вдоль кривой в CSS анимациях поддерживает только Chrome
Анимация SVG
Анимация SVG имеет намного больше возможностей по сравнению с анимацией CSS.
Её логику и сценарий выполнения легко перенастроить в случае необходимости из-за мощной системы логических цепочек условий запуска. Не нужно высчитывать тайминги, как в CSS Просто задаете разные условия в атрибуте begin
#1. Одновременный запуск анимации всех линий
у всех одинаковой условие начала анимаций begin="0s"
.trace{
fill:none;
stroke:#917FDE;
stroke-width:4;
}
#path1 {
stroke-dasharray:50;
stroke-dashoffset:50;
}
#path2 {
stroke-dasharray:121;
stroke-dashoffset:121;
}
#path3 {
stroke-dasharray:150;
stroke-dashoffset:150;
}
#path4 {
stroke-dasharray:56;
stroke-dashoffset:56;
}
#path5 {
stroke-dasharray:331;
stroke-dashoffset:331;
}
<svg version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="568" height="538" viewBox="0 0 568 538" preserveAspectRatio="xMinYMin meet">
<image xlink:href="https://i.stack.imgur.com/n9Btd.jpg" width="100%" height="100%" />
<g id="group">
<path class="trace" id="path1" d="m353.9 285.2 33.6-19.7M281.7 344.2l0.3 10.9" >
<animate attributeName="stroke-dashoffset" begin="0s" dur="2s" repeatCount="1"
values="50;0" restart="whenNotActive" fill="freeze" />
</path>
<path class="trace" id="path2" d="m281.7 344.2 0.3 10.9c0 0 0.1 2.3 0.1 3.6 0 1 0.9 1.1 2.5 2 6.8 3.9 25.2 14 33.7 20.1 0.7 0.5 0.1 7.4 0.3 12 0 1.4-0.3 3.5 0.9 4.3 3.6 2.6 6.3 3.6 10.3 6 8.1 4.8 16.8 9.4 22.9 13.2 4.7 2.9 7.7 4.8 7.7 4.8" >
<animate attributeName="stroke-dashoffset" begin="0s" dur="2s" repeatCount="1"
values="121;0" restart="whenNotActive" fill="freeze" />
</path>
<path class="trace" id="path3" d="m156.4 383 19.9-11.4-0.6-14 34.2-20.2-0.3-67.5 4.6-2.8" >
<animate attributeName="stroke-dashoffset" begin="0s" dur="2s" repeatCount="1"
values="150;0" restart="whenNotActive" fill="freeze" />
</path>
<path class="trace" id="path4" d="M196.3 275.6 148.5 246.5" >
<animate attributeName="stroke-dashoffset" begin="0s" dur="2s" repeatCount="1"
values="56;0" restart="whenNotActive" fill="freeze" />
</path>
<path class="trace" id="path5" d="M414.3 335.1 276.4 414.3c0 0-4.4 2.7-6.8 2.8-2.9 0.2-8.5-2.3-8.5-2.3L127.7 335.1" >
<animate attributeName="stroke-dashoffset" begin="0s" dur="5s" repeatCount="1"
values="331;0" restart="whenNotActive" fill="freeze" />
</path>
</g>
</svg>
#2. Запуск анимаций друг за другом
begin="0s"; begin="1s"; begin="2s"values="50;0;0;50;50"Повторение значений обеспечивает паузы в конечных положениях линии.
.trace{
fill:none;
stroke:#917FDE;
stroke-width:4;
}
#path1 {
stroke-dasharray:50;
stroke-dashoffset:50;
}
#path2 {
stroke-dasharray:121;
stroke-dashoffset:121;
}
#path3 {
stroke-dasharray:150;
stroke-dashoffset:150;
}
#path4 {
stroke-dasharray:56;
stroke-dashoffset:56;
}
#path5 {
stroke-dasharray:331;
stroke-dashoffset:331;
}
<svg version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="568" height="538" viewBox="0 0 568 538" preserveAspectRatio="xMinYMin meet">
<image xlink:href="https://i.stack.imgur.com/n9Btd.jpg" width="100%" height="100%" />
<g id="group">
<path class="trace" id="path1" d="m353.9 285.2 33.6-19.7M281.7 344.2l0.3 10.9" >
<animate attributeName="stroke-dashoffset" begin="0s" dur="2s" repeatCount="indefinite"
values="50;0;0;50;50" restart="whenNotActive" fill="freeze" />
</path>
<path class="trace" id="path2" d="m281.7 344.2 0.3 10.9c0 0 0.1 2.3 0.1 3.6 0 1 0.9 1.1 2.5 2 6.8 3.9 25.2 14 33.7 20.1 0.7 0.5 0.1 7.4 0.3 12 0 1.4-0.3 3.5 0.9 4.3 3.6 2.6 6.3 3.6 10.3 6 8.1 4.8 16.8 9.4 22.9 13.2 4.7 2.9 7.7 4.8 7.7 4.8" >
<animate attributeName="stroke-dashoffset" begin="1s" dur="4s" repeatCount="indefinite"
values="121;0;0;121;121" restart="whenNotActive" fill="freeze" />
</path>
<path class="trace" id="path3" d="m156.4 383 19.9-11.4-0.6-14 34.2-20.2-0.3-67.5 4.6-2.8" >
<animate attributeName="stroke-dashoffset" begin="2s" dur="4s" repeatCount="indefinite"
values="150;0;0;150;150" restart="whenNotActive" fill="freeze" />
</path>
<path class="trace" id="path4" d="M196.3 275.6 148.5 246.5" >
<animate attributeName="stroke-dashoffset" begin="3s" dur="4s" repeatCount="indefinite"
values="56;0;0;56;56" restart="whenNotActive" fill="freeze" />
</path>
<path class="trace" id="path5" d="M414.3 335.1 276.4 414.3c0 0-4.4 2.7-6.8 2.8-2.9 0.2-8.5-2.3-8.5-2.3L127.7 335.1" >
<animate attributeName="stroke-dashoffset" begin="4s" dur="12s" repeatCount="indefinite"
values="331;0;0;331;331" restart="whenNotActive" fill="freeze" />
</path>
</g>
</svg>
#3 Зацикливание анимаций
Когда заканчивается последняя анимация, начинается первая анимация и так по кругу
Достигается это логической цепочкой запуска в первой анимации
begin="0s;an5.end"
.trace{
fill:none;
stroke:#917FDE;
stroke-width:4;
}
#path1 {
stroke-dasharray:50;
stroke-dashoffset:50;
}
#path2 {
stroke-dasharray:121;
stroke-dashoffset:121;
}
#path3 {
stroke-dasharray:150;
stroke-dashoffset:150;
}
#path4 {
stroke-dasharray:56;
stroke-dashoffset:56;
}
#path5 {
stroke-dasharray:331;
stroke-dashoffset:331;
}
<svg version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="568" height="538" viewBox="0 0 568 538" preserveAspectRatio="xMinYMin meet">
<image xlink:href="https://i.stack.imgur.com/n9Btd.jpg" width="100%" height="100%" />
<g id="group">
<!-- Траектория движения растущей линии 1 -->
<path class="trace" id="path1" d="m353.9 285.2 33.6-19.7M281.7 344.2l0.3 10.9" >
<!-- Анимация роста линии -->
<animate id="an1" attributeName="stroke-dashoffset" begin="0s;an5.end" dur="1s" repeatCount="1"
values="50;0" restart="whenNotActive" fill="freeze" />
</path>
<!-- Траектория движения растущей линии 2 -->
<path class="trace" id="path2" d="m281.7 344.2 0.3 10.9c0 0 0.1 2.3 0.1 3.6 0 1 0.9 1.1 2.5 2 6.8 3.9 25.2 14 33.7 20.1 0.7 0.5 0.1 7.4 0.3 12 0 1.4-0.3 3.5 0.9 4.3 3.6 2.6 6.3 3.6 10.3 6 8.1 4.8 16.8 9.4 22.9 13.2 4.7 2.9 7.7 4.8 7.7 4.8" >
<!-- Анимация роста линии 2 -->
<animate id="an2" attributeName="stroke-dashoffset" begin="an1.end" dur="1s" repeatCount="1"
values="121;0" restart="whenNotActive" fill="freeze" />
</path>
<path class="trace" id="path3" d="m156.4 383 19.9-11.4-0.6-14 34.2-20.2-0.3-67.5 4.6-2.8" >
<animate id="an3" attributeName="stroke-dashoffset" begin="an2.end" dur="1s" repeatCount="1"
values="150;0" restart="whenNotActive" fill="freeze" />
</path>
<path class="trace" id="path4" d="M196.3 275.6 148.5 246.5" >
<animate id="an4" attributeName="stroke-dashoffset" begin="an3.end" dur="1s" repeatCount="1"
values="56;0" restart="whenNotActive" fill="freeze" />
</path>
<path class="trace" id="path5" d="M414.3 335.1 276.4 414.3c0 0-4.4 2.7-6.8 2.8-2.9 0.2-8.5-2.3-8.5-2.3L127.7 335.1" >
<animate id="an5" attributeName="stroke-dashoffset" begin="an4.end" dur="1s" repeatCount="1"
values="331;0" restart="whenNotActive" fill="freeze" />
</path>
</g>
</svg>
#4. Зацикленная анимация + движение шарика вдоль криволинейного пути
Мы шли от самых простых примеров с постепенным усложнением. Сейчас добавим ещё движение шарика вдоль пути:
<circle class="c1" cx="0" cy="0" r="4" fill="white" >
<!-- Анимация шарика по траектории -->
<animateMotion begin="an1.end" dur="1s" repeatCount="indefinite" >
<!-- Траектория движения -->
<mpath xlink:href="#path1" />
</animateMotion>
</circle>
Добавлен фильтр Гаусса для легкого размытия краев шарика
.trace{
fill:none;
stroke:#917FDE;
stroke-width:4;
}
#path1 {
stroke-dasharray:5,2;
stroke-dashoffset:50;
}
#path2 {
stroke-dasharray:5,2;
stroke-dashoffset:121;
}
#path3 {
stroke-dasharray:5,2;
stroke-dashoffset:150;
}
#path4 {
stroke-dasharray:5,2;
stroke-dashoffset:56;
}
#path5 {
stroke-dasharray:331;
stroke-dashoffset:331;
}
.c1 {
filter:url(#filterBall);
fill:white;
}
<svg version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="568" height="538" viewBox="0 0 568 538" preserveAspectRatio="xMinYMin meet">
<defs>
<filter id="filterBall" x="-10%" y="-10%" width="160%" height="160%">
<feGaussianBlur stdDeviation="2"/>
</filter>
</defs>
<image xlink:href="https://i.stack.imgur.com/n9Btd.jpg" width="100%" height="100%" />
<g id="group">
<!-- Траектория движения шарика 1 -->
<path class="trace" id="path1" d="m353.9 285.2 33.6-19.7M281.7 344.2l0.3 10.9" >
<animate id="an1" attributeName="stroke-dashoffset" begin="0s" dur="1s" repeatCount="1"
values="50;0" restart="whenNotActive" fill="freeze" />
</path>
<!-- Траектория движения шарика 2 -->
<path class="trace" id="path2" d="m281.7 344.2 0.3 10.9c0 0 0.1 2.3 0.1 3.6 0 1 0.9 1.1 2.5 2 6.8 3.9 25.2 14 33.7 20.1 0.7 0.5 0.1 7.4 0.3 12 0 1.4-0.3 3.5 0.9 4.3 3.6 2.6 6.3 3.6 10.3 6 8.1 4.8 16.8 9.4 22.9 13.2 4.7 2.9 7.7 4.8 7.7 4.8" >
<animate id="an2" attributeName="stroke-dashoffset" begin="an1.end" dur="1s" repeatCount="1"
values="121;0" restart="whenNotActive" fill="freeze" />
</path>
<path class="trace" id="path3" d="m156.4 383 19.9-11.4-0.6-14 34.2-20.2-0.3-67.5 4.6-2.8" >
<animate id="an3" attributeName="stroke-dashoffset" begin="an2.end" dur="1s" repeatCount="1"
values="150;0" restart="whenNotActive" fill="freeze" />
</path>
<path class="trace" id="path4" d="M196.3 275.6 148.5 246.5" >
<animate id="an4" attributeName="stroke-dashoffset" begin="an3.end" dur="1s" repeatCount="1"
values="56;0" restart="whenNotActive" fill="freeze" />
</path>
<path class="trace" id="path5" d="M414.3 335.1 276.4 414.3c0 0-4.4 2.7-6.8 2.8-2.9 0.2-8.5-2.3-8.5-2.3L127.7 335.1" >
<animate id="an5" attributeName="stroke-dashoffset" begin="an4.end" dur="1s" repeatCount="1"
values="331;0" restart="whenNotActive" fill="freeze" />
</path>
</g>
<circle class="c1" cx="0" cy="0" r="4" fill="white" >
<!-- Анимация шарика по траектории -->
<animateMotion begin="an1.end" dur="1s" repeatCount="indefinite" >
<mpath xlink:href="#path1" />
</animateMotion>
</circle>
<circle class="c1" cx="0" cy="0" r="4" fill="white" >
<animateMotion begin="an2.end" dur="1s" repeatCount="indefinite" >
<mpath xlink:href="#path2" />
</animateMotion>
</circle>
<circle class="c1" cx="0" cy="0" r="4" fill="white" >
<animateMotion begin="an3.end" dur="1s" repeatCount="indefinite" >
<mpath xlink:href="#path3" />
</animateMotion>
</circle>
<circle class="c1" cx="0" cy="0" r="4" fill="white" >
<animateMotion begin="an4.end" dur="1s" repeatCount="indefinite" >
<mpath xlink:href="#path4" />
</animateMotion>
</circle>
</svg>


