Windows 7

JavaScript. Разрушение мифов: CSS анимации vs

 JavaScript. Разрушение мифов: CSS анимации vs

Когда-то большинство разработчиков использовало jQuery для анимации элементов в браузере. Обесцветить то, растянуть это – простые вещи. Но когда интерактивные проекты стали более агрессивными, а мобильные устройства ворвались на сцену, производительность стала играть самую важную роль.

Flash постепенно сошел с дистанции, и талантливые аниматоры заставили HTML5 делать вещи, которые он никогда не делал раньше. Им нужны были более эффективные инструменты для сложных эффектов и первоклассной производительности.

jQuery просто не был предназначен для этого. Браузеры повзрослели и начали предлагать решения.

Наиболее широко известным решением стали CSS анимации . CSS анимация как любимец IT-индустрии, на протяжении нескольких лет нескончаемо обсуждалась на конференциях, где такие фразы, как «аппаратное ускорение » и «дружественность мобильным устройствам » ласкали слух аудитории.

Анимации на основе JavaScript рассматривались как устаревшие и «неприличные ». Но так ли это на самом деле?

Будучи тем, кто очарован (на грани одержимости, фактически) анимацией и производительностью, я с нетерпением бросился в объятия CSS. И не успел я далеко продвинуться, как обнаружилось множество серьезных проблем, о которых никто не рассказывал. Я был в шоке.

Эта статья предназначена для повышения осведомленности о некоторых наиболее существенных недостатках анимаций на основе CSS, так что вы сможете избежать головной боли, которую я испытал, и принять более обоснованное решение о том, когда использовать JS для анимации, а когда – CSS.

Отсутствие независимого контроля масштаба/поворота/позиции

Анимация масштаба, поворота и позиции элемента является чрезвычайно распространенной. В CSS все эти параметры запиханы в свойство transform, что делает невозможным создание отдельной анимации для каждого параметра одного элемента.

Например, что если вы хотите сделать анимацию поворота и масштаба независимо друг от друга, с разным расчетом времени выполнения и функциями смягчения?

Может быть, элемент постоянно пульсирует (колеблющийся масштаб), и вам бы хотелось поворачивать его при наведении курсора. Это возможно только с JavaScript.

HTML:

Обратите внимание, что масштаб, поворот и позиция могут быть анимированы независимо друг от друга, с использованием разных функций смягчения и частично перекрывающимся временем начала/конца (что невозможно с CSS-анимациями).

Независимые преобразования Spin rotation Spin rotationX Spin rotationY wander (position)

CSS:

body { background-color:black; margin: 0; padding: 0; font-family: Signika Negative, sans-serif; font-weight: 300; } html, body { height: 100%; } #demo { display:table; width:100%; height:100%; } #field { position:relative; display:table-cell; height: 100%; overflow:hidden; text-align: center; vertical-align: middle; } #box { color: black; font-size:24px; padding: 10px 16px; border: 2px solid black; background: #9af600; background: linear-gradient(to bottom, #9af600 0%,#71B200 100%); display:inline-block; border-radius: 10px; } #field p { position: absolute; color: #999; top: 0px; padding: 0px 20px; text-align: left; z-index: -1000; } #controls { position:absolute; color: #999; width: 100%; bottom: 20px; text-align: center; } button { margin: 2px; }

JS:

var $box = $("#box"), $field = $("#field"), rotation = 0, rotationX = 0, rotationY = 0, wanderTween, ignoreRollovers; //применяем перспективу к контейнеру, чтобы мы могли видеть трехмерность. TweenLite.set($field, {perspective: 500}); //смещаем источник по оси z, чтобы сделать вращение более интересным. TweenLite.set($box, {transformOrigin:"center center -150px"}); //заставляем прямоугольник пульсировать с помощью scaleX и scaleY TweenMax.to($box, 1.2, {scaleX:0.8, scaleY:0.8, force3D:true, yoyo:true, repeat:-1, ease:Power1.easeInOut}); //при наведении, переворачиваем прямоугольник, но чтобы избежать чрезмерного //вращения, мы уменьшим чувствительность к наведению в течение первой секунды //анимации. $box.hover(function() { if (!ignoreRollovers) { rotation += 360; ignoreRollovers = true; TweenLite.to($box, 2, {rotation:rotation, ease:Elastic.easeOut}); TweenLite.delayedCall(1, function() { ignoreRollovers = false; }); } }, function() {}); $("#rotation").click(function() { rotation += 360; TweenLite.to($box, 2, {rotation:rotation, ease:Elastic.easeOut}); }); $("#rotationX").click(function() { rotationX += 360; TweenLite.to($box, 2, {rotationX:rotationX, ease:Power2.easeOut}); }); $("#rotationY").click(function() { rotationY += 360; TweenLite.to($box, 2, {rotationY:rotationY, ease:Power1.easeInOut}); }); $("#move").click(function() { if (wanderTween) { wanderTween.kill(); wanderTween = null; TweenLite.to($box, 0.5, {x:0, y:0}); } else { wander(); } }); //случайно выбираем место на экране и запускаем там анимацию, затем повторяем это //снова и снова. function wander() { var x = (($field.width() - $box.width()) / 2) * (Math.random() * 1.8 - 0.9), y = (($field.height() - $box.height()) / 2) * (Math.random() * 1.4 - 0.7); wanderTween = TweenLite.to($box, 2.5, {x:x, y:y, ease:Power1.easeInOut, onComplete:wander}); }

По моему мнению, это явно слабая сторона CSS, но если вы создаете более простые анимации, которые задействуют преобразования целиком в любой момент времени, тогда этот момент не составит для вас проблему.

Производительность

Большинство сравнений в Интернете противопоставляют CSS анимации и библиотеку jQuery , так как она очень распространена (как если «JavaScript » и «jQuery » были бы синонимами), но широко известно, что jQuery весьма медленная в плане производительности анимации.

Более новая библиотека GSAP также основана на JavaScript, но она буквально в 20 раз быстрее, чем jQuery.. Поэтому одной из причин, из-за которой JavaScript получила плохую репутацию, является, как я его называю, «фактор jQuery ».

Наиболее часто приводимый довод за использование CSS для анимации – это «аппаратное ускорение ». Звучит аппетитно, правда?

Давайте разобьем его на две части:

Вовлечение графического процессора

Графический процессор (GPU) сильно оптимизирован для таких задач, как перемещение пикселей, применение прозрачности и матриц преобразования, поэтому современные браузеры стараются переложить такие задачи с центрального процессора (CPU) на GPU.

Секрет заключается в том, чтобы выделить анимированные элементы в собственные GPU слои, потому что как только слой создан (при условии, что его исходные пикселы не меняются), для GPU не составляет никакого труда перемещать эти пиксели и комбинировать их вместе.

Вместо вычисления каждого отдельного пиксела 60 раз в секунду, GPU может сохранить группы пикселей (как слои) и просто сказать: «Смещаем эту группу на 10 пикселей и на 5 пикселей вниз » (или что-то в этом роде).

Примечание: неразумно выделять каждому элементу свой собственный слой, потому что GPU имеет ограниченную видеопамять. Если вы выйдите за ее пределы, все резко замедлится.

Объявление анимаций в CSS позволяет браузеру определить, какие элементы должны получить слои GPU, и распределить их соответствующим образом. Отлично!

Но знаете ли вы, что с JavaScript вы тоже можете это делать? Установка преобразования с 3D характеристикой (например, translate3d() или matrix3d() ) заставляет браузер создать GPU слой для такого элемента. Так что увеличение скорости с помощью GPU работает не только для CSS анимаций – анимации на JavaScript тоже могут извлечь из этого выгоду!

Также отметим, что не все свойства CSS получают GPU ускорение в CSS анимациях. Фактически, большинство из них этого ускорения как раз не получают. Преобразования (масштаб, поворот, сдвиг и наклон) и прозрачность являются основными операциями, пользующимися выгодами GPU ускорения.

Поэтому не думайте, что если вы создаете анимацию с помощью CSS, то все волшебным образом становится ускоренным GPU. Это просто не соответствует действительности.

Перераспределение вычислений на другой поток

Другая часть «аппаратного ускорения » связана с возможностью использования разных потоков CPU для вычислений, относящихся к анимации. Опять же, это звучит здорово в теории, но не проходит без затрат, и разработчики часто переоценивают получаемые преимущества.

Прежде всего, только те свойства, которые не влияют на поток документа, действительно могут быть переданы другому потоку.

Поэтому снова, преобразования и прозрачность – основные получатели выгоды. При ответвлении потоков появляются накладные расходы, связанные с управлением этим процессом.

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

Например, если 98% работы в течение определенной анимации это рендеринг графики и макет документа, а 2% — выяснение новых значений позиции/поворота/прозрачности/еще чего-то, даже вычисляя их в 10 раз быстрее, в целом вы увидите примерно всего 1% прироста скорости.

Сравнение производительности

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

Задайте большое количество точек и посмотрите сравнение jQuery , GSAP и Zepto .

Поскольку Zepto использует CSS трансформации для всех анимаций, его производительность должна быть самой лучшей, так?

HTML:

  • Engine: jQuery (JS) GSAP (JS) Zepto (CSS)
  • Properties: top, left, width, height transform:translate(...) scale(...)
  • Dots: 25 50 100 200 300 400 500 750 1000 1250 1500 2000 2500 3000
  • START
  • HTML5 тестирование скорости анимации

    Сравните производительность анимаций на основе jQuery, GSAP (GreenSock Animation Platform), и CSS трансформаций (которые используются в Zepto). Выберите параметры выше и нажмите "START". Увеличивайте количество точек, пока не увидите прерывистые движения или скопления/окружности. Также обратите внимание, какие свойства анимируются быстрее: "top", "left", "width" и "height" или "transform: translate(...) scale(...)". Вы, возможно, будете удивлены.

    CSS:

    body { background-color: black; margin:0; padding:0; color:#eee; font-family: Signika Negative, sans-serif; font-weight: 300; font-size: 1.15em; user-select:none; -webkit-user-select:none; } html, body { height: 100%; overflow:hidden; } h1 { font-weight: 400; font-size:2em; line-height:1em; margin-bottom:0.1em; color: white; } a, a:hover, a:visited { color:#71B200; } #controls { display:table-row; background-color:#555; background: linear-gradient(to bottom, #777 0%,#444 100%); padding:10px 10px 10px 5px; z-index:1000; } #controls form li { display:table-cell; padding:12px 6px 10px 6px; vertical-align:middle; text-shadow: 1px 1px 1px #000; } #instructions { width:82%; margin-left:8%; padding-top:1em; line-height: 1.5em; color:#ccc; } #demo { display:table; width:100%; height:100%; } #field { position:relative; display:table-cell; width:100%; height: 100%; overflow:hidden; z-index:-100; border-top: 1px solid #777; } #start { color: black; border-radius: 6px; padding: 5px 18px; border: 2px solid black; background: #9af600; background: linear-gradient(to bottom, #9af600 0%,#71B200 100%); cursor: pointer; text-shadow: none; font-weight: 400; }

    JS:

    var $start = $("#start"), $dotQtyInput = $("#dotQuantity"), $engineInput = $("#engine"), $propertiesInput = $("#properties"), $instructions = $("#instructions"), $field = $("#field"), $window = $(window), $inputs = $("select"), inProgress = false, tests = {}, duration, radius, centerX, centerY, dots, rawDots, currentTest, startingCSS; /** * Целью этого теста является сравнение того, как различные инструменты для создания анимаций работают при нагрузке, получая относительно распространенные анимационные задачи и выполняя их в большом количестве, чтобы увидеть чистую производительность. Целью не является выяснение самого эффективного способа перемещения точек в шаблоне звездного поля. * * Одинаковый код использован во всем за исключением самих анимаций. Каждый тест в объекте “test” имеет 4 свойства: * * - milliseconds – имеет значение true, если продолжительность должна быть определенна в миллисекундах * * - wrapDot – когда каждая точка создается, она должна быть передана в метод wrapDot() и то, что возвращается функцией, сохраняется в массиве точек для анимации. Это полезно для повышения производительности таких вещей, как jQuery, потому что вместо передачи DOM элемента в метод tween() (который потребует jQuery запросить DOM и обернуть элемент в специфичный для движка объект до вызова animate()) может быть использован естественный объект. Проще говоря, это позволит кэшировать обертывание точек для повышения производительности. * * - tween – это ядро всего теста. tween() вызывается для каждой точки, точка передается в качестве параметра. Функция tween() должна устанавливать cssText точки в значение startingCSS (которое просто помещает точку в середину экрана и устанавливает значение для ее ширины и высоты в 1 пиксель) и затем после произвольной задержки длительностью от 0 до времени выполнения анимации, функция должна анимировать точку под случайным углом, изменяя либо значения left/top, либо преобразования translate(), и устанавливать размер в 32 пикселя в ширину и высоту, используя либо width/height, либо scale(). Затем, после завершения анимации, метод tween() должен быть вызван снова для этой же точки. Так что та же самая точка просто будет постоянно двигаться от центра под случайным углом и с произвольным временем задержки. * * - stop – эта функция вызывается, когда пользователь останавливает тест. Точка передается в качестве параметра. Функция должна тотчас остановить/уничтожить анимацию (или анимации), запущенные для этой точки (или для всех точек – это тоже нормально). * * - nativeSize – имеет значение true, если начальные width/height изображения должны быть в натуральную величину (обычно необходимо для преобразований, но не когда мы анимируем width/height). * *Я не претендую на звание эксперта в разнообразных движках для анимации, поэтому, если есть пути оптимизации, которые можно применить, чтобы улучшить выполнение теста, пожалуйста, дайте мне знать. Я пытался сделать все максимально беспристрастно. **/ //стандартный jQuery normal (top/left/width/height) tests.jquery_normal = { milliseconds:true, wrapDot:function(dot) { return jQuery(dot); //заворачиваем точку в объект jQuery для повышения производительности (таким образом, нам не нужно запрашивать DOM каждый раз, когда мы анимируем – мы можем просто вызвать animate() прямо для объекта jQuery) }, tween:function(dot) { var angle = Math.random() * Math.PI * 2; dot.style.cssText = startingCSS; dot.delay(Math.random() * duration).animate({left:Math.cos(angle) * radius + centerX, top:Math.sin(angle) * radius + centerY, width:32, height:32}, duration, "cubicIn", function() { tests.jquery_normal.tween(dot) }); }, stop:function(dot) { dot.stop(true); }, nativeSize:false }; //стандартный GSAP (top/left/width/height) tests.gsap_normal = { milliseconds:false, wrapDot:function(dot) { return dot; //нет необходимости в обертывании }, tween:function(dot) { var angle = Math.random() * Math.PI * 2; dot.style.cssText = startingCSS; TweenLite.to(dot, duration, {css:{left:Math.cos(angle) * radius + centerX, top:Math.sin(angle) * radius + centerY, width:32, height:32}, delay:Math.random() * duration, ease:Cubic.easeIn, overwrite:"none", onComplete:tests.gsap_normal.tween, onCompleteParams:}); }, stop:function(dot) { TweenLite.killTweensOf(dot); }, nativeSize:false }; //GSAP преобразования (translate()/scale()) tests.gsap_transforms = { milliseconds:false, wrapDot:function(dot) { return dot; // нет необходимости в обертывании }, tween:function(dot) { var angle = Math.random() * Math.PI * 2; TweenLite.set(dot, {css:{x:0, y:0, scale:0.06}, overwrite:"none"}); TweenLite.to(dot, duration, {css:{x:(Math.cos(angle) * radius), y:(Math.sin(angle) * radius), scaleX:2, scaleY:2}, delay:Math.random() * duration, ease:Cubic.easeIn, overwrite:"none", onComplete:tests.gsap_transforms.tween, onCompleteParams:}); }, stop:function(dot) { TweenLite.killTweensOf(dot); }, nativeSize:true }; //стандартный Zepto (top/left/width/height) tests.zepto_normal = { milliseconds:true, wrapDot:function(dot) { return Zepto(dot); // заворачиваем точку в объект jQuery для повышения производительности (таким образом, нам не нужно запрашивать DOM каждый раз, когда мы анимируем – мы можем просто вызвать animate() прямо для объекта jQuery) }, tween:function(dot) { var angle = Math.random() * Math.PI * 2; dot.style.cssText = startingCSS; //Функция задержки в Zepto под давлением работает УЖАСНО, поэтому вместо нее мы используем функцию setTimeout() для повышения производительности. setTimeout(function() { if (!dot.isKilled) { //Zepto не имеет функции, которая позволила бы нам уничтожить запущенные анимации, поэтому мы просто устанавливаем наше собственное свойство isKilled в значение true, когда предполагается, что анимация прекращена и затем останавливаем рекурсию, что дает нам необходимый эффект. dot.animate({left:Math.cos(angle) * radius + centerX, top:Math.sin(angle) * radius + centerY, width:32, height:32}, duration, "cubic-bezier(0.550, 0.055, 0.675, 0.190)", function() { tests.zepto_normal.tween(dot) }); } }, duration * Math.random()); }, stop:function(dot) { dot.isKilled = true; }, nativeSize:false }; //Zepto преобразования (translate()/scale()) tests.zepto_transforms = { milliseconds:true, wrapDot:function(dot) { return Zepto(dot); // заворачиваем точку в объект jQuery для повышения производительности (таким образом, нам не нужно запрашивать DOM каждый раз, когда мы анимируем – мы можем просто вызвать animate() прямо для объекта jQuery) }, tween:function(dot) { // Мне не удалось задать функцию css() в Zepto (она не выполнилась), поэтому пришлось использовать вызов animate() нулевой длительности. Хотя это справедливо, потому что для TweenLite мы, на самом деле, тоже делаем анимацию нулевой длительности. dot.animate({translateX:"0px", translateY:"0px", rotateY:"0rad", rotateX:"0rad", scale:"0.06,0.06"},0); // Функция задержки в Zepto под давлением работает УЖАСНО, поэтому вместо нее мы используем функцию setTimeout() для повышения производительности. setTimeout(function() { if (!dot.isKilled) { //Zepto не имеет функции, которая позволила бы нам уничтожить запущенные анимации, поэтому мы просто устанавливаем наше собственное свойство isKilled в значение true, когда предполагается, что анимация прекращена и затем останавливаем рекурсию, что дает нам необходимый эффект. var angle = Math.random() * Math.PI * 2; dot.animate({translateX:(Math.cos(angle) * radius) + "px", translateY:(Math.sin(angle) * radius) + "px", scale:"2,2", delay:duration * Math.random()}, duration, "cubic-bezier(0.550, 0.055, 0.675, 0.190)", function() { tests.zepto_transforms.tween(dot); }); } }, duration * Math.random()); }, stop:function(dot) { dot.isKilled = true; }, nativeSize:true }; function toggleTest() { var i, size; inProgress = !inProgress; if (inProgress) { $inputs.prop("disabled", true); $field.css({pointerEvents:"none"}); //улучшаем производительность – игнорируем события указателя во время анимации $start.html(" STOP "); $start.css({background:"#C00"}); TweenLite.to($instructions, 0.7, {autoAlpha:0, overwrite:"all"}); currentTest = tests[$engineInput.val() + "_" + $propertiesInput.val()]; size = (currentTest.nativeSize ? "16px" : "1px"); centerX = $field.width() / 2; centerY = $field.height() / 2; startingCSS = "position:absolute; left:" + centerX + "px; top:" + centerY + "px; width:" + size + "; height:" + size + ";"; radius = Math.sqrt(centerX * centerX + centerY * centerY); duration = currentTest.milliseconds ? 750: 0.75; //ждем миллисекунду прежде чем создавать точки и начать анимацию, поэтому пользовательский интерфейс воспроизводится вперед (превращая кнопку «старт» в «стоп»), в противном случае пользователи могли бы запутаться во время длительной паузы, когда выбран Zepto и преобразования, в связи с тем, что возможно, это займет некоторое время, пока браузер поместит все точки на их собственные слои. setTimeout(function() { createDots(); i = dots.length; while (--i > -1) { currentTest.tween(dots[i]); } }, 1); } else { $start.html(" START "); $start.css({backgroundColor:"#9af600", background: "linear-gradient(to bottom, #9af600 0%,#71B200 100%"}); TweenLite.to($instructions, 0.7, {autoAlpha:1, delay:0.2}); $inputs.prop("disabled", false); calibrateInputs(); $field.css({pointerEvents:"auto"}); //останавливаем анимацию и удаляем точки. i = dots.length; while (--i > -1) { currentTest.stop(dots[i]); $field.removeChild(rawDots[i]); //удаляет точку (или точки) } dots = null; rawDots = null; } } function createDots() { var i = parseInt($dotQtyInput.val()), dot; dots = ; rawDots = ; while (--i > -1) { dot = document.createElement("img"); dot.src = "https://s3-us-west-2.amazonaws.com/s.cdpn.io/16327/dot.png"; dot.width = 1; dot.height = 1; dot.id = "dot" + i; dot.style.cssText = startingCSS; $field.appendChild(dot); rawDots.push(dot); dots.push(currentTest.wrapDot(dot)); } } function calibrateInputs(e) { if ($engineInput.val() === "jquery") { //jQuery не может анимировать преобразования без стороннего плагина, поэтому отключаем эту опцию $propertiesInput.selectedIndex = 0; $propertiesInput.prop("disabled", true); } else { $propertiesInput.prop("disabled", false); } } $start.click(toggleTest); $inputs.change(calibrateInputs); jQuery.easing.cubicIn = $.easing.cubicIn = function(p, n, firstNum, diff) { //нам нужно добавить стандартную функцию смягчения CubicIn в jQuery return firstNum + p * p * p * diff; } jQuery.fx.interval = 16; //гарантирует, что jQuery обновляет примерно 60 кадров в секунду, как GSAP и другие, чтобы показать более равный/беспристрастный результат. $propertiesInput.prop("disabled", true);

    Результаты подтверждают то, что широко отмечается в Интернете – CSS анимации значительно быстрее, чем jQuery.

    Однако на большинстве устройств и браузеров, в которых я проводил тестирование, GSAP на основе JavaScript имеет даже лучшую производительность, чем CSS анимации (с большим отрывом в некоторых случаях, как например, на Microsoft Surface RT где библиотека GSAP была по крайней мере в 5 раз быстрее, чем CSS трансформации, созданные с помощью Zepto , и на iPad 3 с iOS7 преобразования были гораздо быстрее, когда выполнялись с помощью GSAP вместо CSS трансформаций):

    Анимированные свойства Лучше с JavaScript Лучше с CSS
    top, left, width, height Windows Surface RT, iPhone 5s (iOS7), iPad 3 (iOS 6), iPad 3 (iOS7), Samsung Galaxy Tab 2, Chrome, Firefox, Safari, Opera, Kindle Fire HD, IE11
    преобразования (сдвиг/масштаб) Windows Surface RT, iPhone 5s (iOS7), iPad 3 (iOS7), Samsung Galaxy Tab 2, Firefox, Opera, IE11 iPad 3 (iOS6), Safari, Chrome

    Насколько быстрее? Первоначальная версия теста имела счетчик количества кадров в секунду для получения количественных результатов, но вскоре обнаружилось, что нет никакого по-настоящему точного способа измерить этот показатель во всех браузерах, особенно с CSS анимациями, и некоторые браузеры выдавали вводящие в заблуждение данные, поэтому я удалил эту функцию.

    Хотя вы легко можете оценить относительную производительность, увеличивая количество точек, переключаясь между движками и наблюдая, как происходит выполнение анимации (плавность движения, равномерность промежутков времени, распределение точек и т.п.). В конце концов, главная цель состоит в том, чтобы получить презентабельные анимации.

    Интересно отметить:

    • При анимации свойств top/left/width/height (влияющих на поток документа) JavaScript был быстрее по всем направлениям (GSAP, не jQuery);
    • Некоторые устройства оказались хорошо оптимизированными для преобразований, в то время как другие лучше обрабатывали анимации со свойствами top/left/width/height. В частности, более старая iOS6 выполняла преобразования на основе CSS намного лучше, а новая iOS7 сменила приоритеты, и сейчас они выполняются значительно медленнее;
    • Существует значительная задержка в первоначальном запуске анимации на основе CSS, так как браузер вычислят слои и загружает данные в GPU. Это также применимо и к трехмерным преобразованиям на JavaScript, поэтому «ускорение с GPU» не проходит без потерь;
    • При сильных нагрузках CSS трансформации с большей вероятностью распыляются в полосы или кольца (это связано с проблемами синхронизации и планирования, возможно, из-за управления в другом потоке);
    • В некоторых браузерах (например, Google Chrome), когда в анимации было задействовано очень большое количество точек, совершенно отсутствовало постепенное затухание текста, но происходило это только при использовании CSS анимаций!

    Хотя хорошо оптимизированный JavaScript часто работает настолько же быстро, если не быстрее, чем CSS анимации, трехмерные преобразования, как правило, воспроизводятся с помощью CSS, но это непосредственно связано с тем, как браузеры обрабатывают 16-элементные матрицы (вынуждая конвертировать из чисел в конкатенированную строку, а потом назад в числа).

    Хотя будем надеяться, что это изменится. Как бы то ни было, в большинстве реальных проектов вы никогда бы не заметили разницу в производительности.

    Я призываю вас провести собственное тестирование, чтобы посмотреть какая технология обеспечит плавную анимацию в конкретном проекте(ах).

    Не покупайтесь на миф, что CSS анимации всегда быстрее, и не считайте, что тест на скорость, приведенный выше, отражает то, что вы увидите в вашем приложении. Тестируйте, тестируйте и еще раз тестируйте.

    Элементы управления выполнением и события

    Некоторые браузеры позволяют остановить или перезапустить анимацию с ключевыми кадрами CSS, но на этом – все.

    Вы не можете обратиться к конкретному месту в анимации, также как не можете плавно поменять направление хода на участке анимации, или изменить шкалу времени, или добавить обратные вызовы в определенных местах, или привязать их к богатому набору событий воспроизведения.

    JavaScript, напротив, предоставляет большие возможности для контроля, как можно увидеть в примере ниже.

    HTML:

    Невозможно с CSS анимациями. play reverse restart Speed: slow normal fast

    CSS:

    body { font-family: Signika Negative, sans-serif; font-weight: 300; color: white; background-color: black; text-align: center; } #demo { text-align: center; margin-top:20px; } #bg { background-color:#000; position:relative; overflow:hidden; display:inline-block; width:500px; height:70px; border-radius: 8px; border: 2px solid #777; } #text { position:absolute; text-align:center; width:500px; height:70px; line-height:68px; font-size: 28px; } #text span { -webkit-font-smoothing: antialiased; -moz-font-smoothing:antialiased; position:relative; display:inline-block; color:#FFF; } #slider { display: inline-block; width: 500px; height:12px; margin:8px 0px 8px 6px; } #controls button { width: 80px; } #controls input { display:inline; padding:2px; margin:2px; }

    JS:

    var $text = $("#text"), $pause = $("#pause"), $reverse = $("#reverse"), $restart = $("#restart"), $speed = $("input"), $slider = $("#slider"), //"tl" является шкалой, к которой мы добавим нашу анимацию. //Тогда мы сможем легко контролировать всю последовательность выполнения //анимации как один объект. tl = new TimelineLite({onUpdate:updateSlider, onComplete:onComplete, onReverseComplete:onComplete, paused:true}); function updateSlider() { $slider.slider("value", tl.progress() * 100); } function onComplete() { tl.pause(); $pause.html("play"); } //делаем простое разделение текста, чтобы мы могли применить анимацию к каждому //символу (не нужны расширенные функции SplitText, поэтому просто используем split() и //join()) $text.html("" + $text.html().split("").join("").split("").join("") + ""); //устанавливаем перспективу на контейнере TweenLite.set($text, {perspective:500}); //вся анимация создается в одной строке: tl.staggerTo($("#text span"), 4, {transformOrigin:"50% 50% -30px", rotationY:-360, rotationX:360, rotation:360, ease:Elastic.easeInOut}, 0.02); //управление ползунком и кнопкой $slider.slider({ range: false, min: 0, max: 100, step:.1, slide: function (event, ui) { tl.progress(ui.value / 100).pause(); $pause.html("play"); } }); $pause.click(function() { if (tl.paused()) { if (tl.progress() === 1 || (tl.progress() === 0 && tl.reversed())) { tl.restart(); } else { tl.resume(); } $pause.html("pause"); } else { tl.pause(); $pause.html("resume"); } }); $reverse.click(function() { if (tl.progress() === 0) { if (tl.reversed()) { tl.play(); } else { tl.reverse(0); } $pause.html("pause"); } else { tl.reversed(!tl.reversed()).resume(); $pause.html("pause"); } }); $restart.click(function(){ tl.restart(); $pause.html("pause"); }); $speed.change(function(v, val) { tl.timeScale(parseFloat($(this).val())); if (tl.progress() === 1) { tl.restart(); $pause.html("pause"); } else if (tl.paused()) { tl.resume(); $pause.html("pause"); } });

    Современная анимация очень сильно связана с интерактивностью, поэтому невероятно полезно иметь возможность выполнять анимацию от изменяемых начальных значений до изменяемых конечных (например, зависящих от того, в каком месте пользователь щелкнет мышью) или изменить что-то «на лету », но декларативные анимации на основе CSS не позволяют сделать это.

    Рабочий процесс

    Для простых переходов между двумя состояниями (например, перевороты или раскрытие меню, и т.п.) отлично подходят CSS трансформации.

    Однако, для последовательности событий вам, как правило, потребуется использовать анимации CSS с ключевыми кадрами, в которых обязательно нужно определять селекторы в виде процентов, например:

    CSS:

    @keyframes myAnimation { 0% { opacity: 0; transform: translate(0, 0); } 30% { opacity: 1; transform: translate(0, 0); } 60% { transform: translate(100px, 0); } 100% { transform: translate(100px, 100px); } } #box { animation: myAnimation 2.75s; }

    Но когда вы создаете анимацию, разве вы не ориентируетесь с помощью временных интервалов, а не процентов? Например, «увеличить прозрачность в течение 1 секунды, потом сдвигать вправо в течение 0,75 секунды, и затем на оставшейся секунде сделать скачок вниз ».

    Что произойдет, если вы потратите несколько часов на вычисление сложной последовательности в процентах, а клиент затем скажет: «Сделайте эту часть в середине на 3 секунды дольше »? Уфф, вам придется пересчитывать ВСЕ проценты!

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

    Это актуально там, где метод seek() оказался бы достаточно полезным. Представьте себе создание 60-секундной анимации кусочек за кусочком, а затем оттачивание заключительных 5 секунд: вам пришлось бы просиживать первые 55 секунд каждый раз, когда вы хотите посмотреть результат ваших корректировок в последних частях.

    Фу! С помощью метода seek() вы могли бы в процессе работы просто сослаться на определенное место анимации, чтобы попасть в ту часть, над которой работаете, а затем удалить его, когда закончите. Это значительная экономия времени.

    Широкое распространение получает создание анимации для объектов на основе canvas и других объектов сторонних библиотек, но, к сожалению, CSS анимации предназначены только для DOM элементов.

    Это значит, что если вы вложили много времени и энергии в CSS анимации, их нельзя будет перенести в другие типы проектов.

    Вы должны будете изменить набор инструментов для анимации.

    Существует еще несколько удобных инструментов, относящихся к рабочему процессу, которые отсутствуют в CSS анимациях:

    • Относительные величины . Например, «сделать поворот на 30 градусов больше » или «переместить элемент вниз на 100 пикселей от места, где он находился, когда началась анимация »;
    • Вложенность . Представьте себе возможность создавать анимации, которые могут быть вложены в другую анимацию, которая сама может вложенной и т.д. Вообразите управление главной анимацией, в то время как все остальное остается полностью синхронизировано. Такая структура способствовала бы модульному коду, который намного легче создавать и поддерживать;
    • Отчет о ходе выполнения . Завершена ли конкретная анимация? Если нет, то на какой точно стадии выполнения она находится?
    • Целевые ликвидации . Иногда невероятно полезно ликвидировать все анимации, которые влияют на масштаб элемента (или любое другое свойство по вашему желанию), разрешив при этом все остальные;
    • Краткий код . CSS анимации на основе ключевых кадров отличаются многословностью, даже если не учитывать необходимость всех избыточных вендорно-префиксных версий. Любой, кто пытался создать что-то даже средней сложности, подтвердит тот факт, что CSS анимации быстро становятся громоздкими и неуклюжими. На самом деле, реальный объем CSS кода, необходимого для выполнения задач по анимации, может превышать вес библиотеки JavaScript (которую легче поместить в кэш и использовать повторно во многих анимациях).
    Ограниченные эффекты

    Вы не сможете сделать ничего из нижеследующего списка при помощи CSS анимации:

    • Анимация вдоль кривой (например, кривой Безье);
    • Использование интересных функций смягчения, таких как упругое, пружинистое или грубое смягчение. Существует опция cubic-bezier() , но она допускает только две ключевые точки, что сильно ограничивает возможности;
    • Движения по физическим законам. Например, плавное перемещение на основе инерции и легкое возвращение назад, реализованное в этом Draggable demo ;
    • Анимация позиции прокрутки;
    • Направленный поворот (например, «повернуть ровно на 270 градусов в кратчайшем направлении, по часовой или против часовой стрелки »);
    • Анимация атрибутов.
    Совместимость

    Анимации на основе CSS не работают в IE9 и более ранних версиях браузера. Большинство из нас ненавидят обеспечивать поддержку устаревших браузеров (особенно IE), но реальность такова, что у некоторых из нас есть клиенты, которые требуют сделать это.

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

    Заключение

    Плохи ли CSS анимации? Определенно нет. Фактически, они отлично подходят для простых переходов между состояниями (например, переворачивания), когда не требуется совместимость с устаревшими браузерами.

    Трехмерные преобразования обычно имеют хорошую производительность (iOS7 является примечательным исключением) и CSS анимации могут быть очень привлекательны для разработчиков, предпочитающих помещать всю логику анимаций и презентаций в слой CSS.

    Однако анимации на основе JavaScript предоставляют гораздо большую гибкость, более комфортный процесс разработки для сложных анимаций и роскошную возможность интерактивного взаимодействия, и часто анимации на JavaScript выполняются также быстро (или даже быстрее) как и анимации на основе CSS, несмотря на то, что вы, возможно, слышали.

    Я могу понять, почему CSS анимации были такими привлекательными по сравнению с jQuery.animate() . Кто в здравом уме не ухватился бы за возможность получить 10-кратный прирост производительности?

    Теперь нет необходимости выбирать между jQuery и CSS анимациями, инструменты на основе JavaScript, такие как GSAP , открывают совершенно новые возможности и сокращают разрыв в производительности.

    Это статья – не о GSAP или какой-либо определенной библиотеке; мораль статьи в том, что анимации на основе JavaScript не заслуживают плохой репутации. Фактически, JavaScript является единственным вариантом для по-настоящему надежной и гибкой системы анимации.

    Плюс, я хотел пролить немного света на некоторые стороны CSS анимаций, вызывающие разочарование (о которых никто не говорит), так что теперь вы можете принять более обоснованное решение о том, как создавать анимации.

    Решит ли спецификация Web Animations существующие проблемы?

    Консорциум W3C работает над новой спецификацией под названием «Web Animations » (веб-анимации), целью которой является решение многих недостатков в CSS анимациях и трансформациях, обеспечение лучшего контроля выполнения и дополнительных функций.

    Конечно, кажется, что это шаг вперед во многих отношениях, но все еще есть ряд недостатков (некоторые их которых, вероятно, невозможно преодолеть из-за необходимости поддержки старых версий существующих CSS спецификаций, поэтому, например, независимое управление компонентами преобразования маловероятно).

    Хотя эту уже совсем другая история. Нам необходимо подождать и посмотреть, как все сложится. Есть, несомненно, умные ребята, работающие над этой спецификацией.

    Данная публикация представляет собой перевод статьи «Myth Busting: CSS Animations vs. JavaScript » , подготовленной дружной командой проекта

    В ы можете использовать JavaScript для создания сложной анимации, но не ограничиваясь, следующие элементы:

    • Фейерверк
    • Эффект затемнения
    • Сворачивание или разворачивание.
    • Переход на страницу или выход из страницы
    • Движения объектов

    Вам может быть интересна существующая анимационная библиотека на основе JavaScript: Script.Aculo.us.

    В этой статье представлено базовое представление о том, как использовать JavaScript для создания анимации.

    JavaScript может использоваться для перемещения нескольких элементов DOM (, или любого другого элемента HTML) на страницах в соответствии с каким-либо шаблоном, определяемым логическим уравнением или функцией.

    JavaScript предоставляет следующие две функции, которые часто используются в анимационных программах.

    • setTimeout(function, duration) – эта функция вызывает function после duration миллисекунд, начиная с момента вызова.
    • setInterval(function, duration) – эта функция вызывает function после каждой duration миллисекунды.
    • clearTimeout(setTimeout_variable) – эта функция вызывает очистку любого таймера, установленного функциями setTimeout().

    JavaScript также может устанавливать несколько атрибутов объекта , включая его положение на экране. Вы можете установить атрибут top и left объекта, чтобы поместить его в любом месте на экране. Вот его синтаксис.

    // Установите расстояние от левого края экрана. object.style.left = distance in pixels or points; или // Заданном расстоянии от верхнего края экрана. object.style.top = distance in pixels or points;

    Ручная анимация

    Итак, давайте реализуем одну простую анимацию с использованием свойств объекта DOM и функций JavaScript следующим образом. Следующий список содержит различные методы DOM.

    • Мы используем функцию JavaScript getElementById() для получения объекта DOM, а затем присваиваем ему глобальную переменную imgObj .
    • Мы инициализировали функциюinit() для инициализации imgObj, где мы установили ее атрибуты position и left .
    • Мы вызываем функцию инициализации во время загрузки окна.
    • Наконец, мы вызываем функцию moveRight(), чтобы увеличить левое расстояние на 10 пикселей. Вы также можете установить его на отрицательное значение, чтобы переместить его влево.
    Пример

    Попробуйте следующий пример.

    Анимация в JavaScript

    Нажмите кнопку ниже, чтобы переместить изображение вправо

    Автоматическая анимация

    В приведенном выше примере мы увидели, как изображение перемещается вправо с каждым щелчком. Мы можем автоматизировать этот процесс, используя функцию setTimeout() в JavaScript следующим образом:

    • Функция moveRight() вызывает функцию setTimeout() для установки позиции imgObj .
    • Мы добавили новую функцию stop(), чтобы очистить таймер, установленный функцией setTimeout(), и установить объект в его исходное положение.
    Пример

    Попробуйте следующий пример кода.

    Анимация в JavaScript

    Нажмите кнопки ниже, чтобы обработать анимацию

    Ролловер с событием мыши

    Вот простой пример, показывающий опрокидывание изображения с событием мыши.

    Давайте посмотрим, что мы используем в следующем примере:

    • Во время загрузки этой страницы оператор «if» проверяет наличие объекта изображения. Если объект изображения недоступен, этот блок не будет выполнен.
    • Конструктор Image() создает и предварительно загружает новый объект изображения с именем image1 .
    • Свойству src присваивается имя файла внешнего изображения, называемого /images/html.gif.
    • Аналогично, мы создали объект image2 и назначаем /images/http.gif этому объекту.
    • Символ # (хэш-знак) отключает ссылку, чтобы браузер не пытался перейти к URL-адресу при нажатии. Эта ссылка является изображением.
    • Обработчик события OnMouseOver вызывается, когда пользователь движет мышь на ссылке, и обработчик события onMouseOut вызывается, когда мышь пользователя отходит от линии (изображение).
    • Когда мышь перемещается по изображению, изображение изменяется с первого изображения на второе. Когда мышь перемещается от изображения, отображается исходное изображение.
    • Когда мышь будет удалена от ссылки, на экране появится исходное изображение html.gif.
    Ролловер с событиями мыши

    Наведите курсор на изображение, чтобы увидеть результат

    Аннотация: Простой пример: метод угасания желтого цвета. Анимация с помощью библиотек JavaScript. Более сложный пример: перемещение и изменение размера. Переходы CSS.

    Принцип в основе угасания состоит в том, что задается желтый цвет фона элемента угасания, а затем, за некоторую последовательность шагов его цвет возвращается к исходному. Поэтому, если исходный цвет фона был красный, то затем цвет задается желтым, затем оранжево-желтым, затем оранжевым, затем красно-оранжевым, и затем красным. Число использованных шагов определяет, насколько плавно происходит изменение цвета, а время между шагами определяет, как долго продолжается изменение цвета. При изменении цвета можно использовать полезный факт из CSS : цвет можно определить как тройку обычных чисел или как шестнадцатеричную строку. Поэтому #FF0000 (красный цвет) можно определить также как rgb(255,0,0) . Изменение от желтого цвета до красного за пять шагов означает, поэтому, переход от rgb(255,255,0) (желтый) к rgb(255,0,0) за пять следующих шагов:

    rgb(255,255,0) rgb(255,192,0) rgb(255,128,0) rgb(255,64,0) rgb(255,0,0)

    Более сложный пример: перемещение и изменение размера

    Хотя метод угасания желтого цвета демонстрирует анимацию, он несколько скучен. Когда большинство людей представляют себе анимацию, они обычно имеют в виду движение. Интересный прием предупреждения пользователя о том, что что-то произошло, не прерывая его рабочего процесса , состоит в немодальном сообщении. Вместо вывода диалогового окна alert() , которое требует от пользователя щелчка на OK , прежде чем он сможет продолжить, поместите сообщение просто в плавающий div на странице, который ненавязчиво остается там, пока не получит подтверждение. Второй достаточно интересной вещью затем может быть предоставление пользователю возможности вернуться к сообщению, для которого он подтвердил желание прочитать его еще раз. Поэтому давайте реализуем плавающее сообщение, которое, после щелчка на нем, "схлопывается" в угол экрана, и затем по щелчку может быть снова восстановлено. Вы можете посмотреть небольшую демонстрацию такого "схлопывающегося сообщения" (http://dev.opera.com/articles/view/javascript-animation/moving_messages_jq.html), чтобы понять общую идею.

    Если вы делаете какую-то серьезную анимационную работу, или какую-то серьезную работу с JavaScript, почти всегда стоит использовать библиотеку JavaScript. Это позволит создать требуемое представление для пользователей, не беспокоясь о математических тонкостях, требуемых для выполнения анимации. (Познакомившись с представленным выше первым примером, вы знаете теперь, как выполнить математические вычисления и как использовать setInterval , но вы сохраните время и собственные силы, используя готовые решения.)

    Приведенный выше демонстрационный пример использует для работы библиотеку jQuery (http://jquery.com/), но как упоминалось, большинство библиотек предоставляют достаточно похожую концепцию анимации, и поэтому вы сможете реализовать принципиальную часть, используя предпочитаемую библиотеку. По существу, необходимо сделать следующее:

  • Показать плавающее сообщение в центре экрана
  • Когда на нем производится щелчок:
  • Переместить его горизонтальную позицию в крайнее правое положение
  • Переместить его вертикальную позицию вверх
  • Задать его ширину равной 20px
  • Задать его высоту равной 20px
  • Сделать его плотность равной 20%, так что оно становится почти прозрачно и скрыть в нем текст
  • Когда выполняется щелчок на этой "мини"-версии сообщения, восстановить его в центре экрана (т.е., обратное тому, что мы делали для его сжатия) и чтобы пользователь получил четкую картину того, что произошло с его сообщением, переход от полноразмерного сообщения к мини-сообщению должен быть анимирован (чтобы они видели, что сообщение "сжалось" в угол окна).
  • Выполнить анимацию с помощью jQuery очень легко: используйте просто функцию . animate () и предоставьте желательный конечный результат анимации (и как долго она должна выполняться):

    $(ourObject).animate({ width: "20px", height: "20px", top: "20px", right: "20px", marginRight: "0px", opacity: "0.2" }, 300);

    Функция получает ourObject и, за 300 миллисекунд, заменяет его ширину и высоту на 20px, его верхнюю и правую позиции на 20px, его свойство стиля margin-right на 0px, и его плотность (в браузерах, которые поддерживают плотность изображения) на 20%. Затем это просто вопрос программирования в стиле

    Создание анимации на базе JavaScript с помощью библиотеки Anime.js. Часть 1

    DOM-узлы (DOM node) или коллекция узлов (NodeList): вы можете также использовать DOM-узел или NodeList в качестве значения для ключевого слова targets . Посмотрите на пример использования DOM-узла для targets .

    Var special = anime({ targets: document.getElementById("special"), translateY: 200 }); var blue = anime({ targets: document.querySelector(".blue"), translateY: 200 }); var redBlue = anime({ targets: document.querySelectorAll(".red, .blue"), translateY: 200 }); var even = anime({ targets: document.querySelectorAll(".square:nth-child(even)"), translateY: 200 }); var notRed = anime({ targets: document.querySelectorAll(".square:not(.red)"), translateY: 200 });

    В первом случае использовалась функция getElementById() , чтобы обратиться к определённому элементу. Функция querySelector() использовалась для обращения к элементу с классом blue . А функция querySelectorAll() применялась для обращения ко всем элементам внутри документа, которые соответствуют группе определённых селекторов или же, наоборот, не входят в неё.

    Существует множество функций, которые вы также можете использовать для выбора целевого элемента. Например, вы можете обратиться к элементам с определённым классом, используя функцию getElementsByClassName() . Или к элементам с определённым тегом, используя функцию getElementsByTagName() .

    Любая функция, возвращающая DOM-узел или NodeList, может использоваться для установки значения targets в Anime.js.

    Объект: вы можете использовать объекты JavaScript в качестве значения для targets . Ключ этого объекта используется в качестве идентификатора, а значение - в качестве числа, которое нужно анимировать.

    Затем вы сможете показать анимацию внутри другого HTML-элемента с помощью дополнительного JavaScript-кода. Ниже приведён пример анимации значений двух разных ключей одного объекта.

    Var filesScanned = { count: 0, infected: 0 }; var scanning = anime({ targets: filesScanned, count: 1000, infected: 8, round: 1, update: function() { var scanCount = document.querySelector(".scan-count"); scanCount.innerHTML = filesScanned.count; var infectedCount = document.querySelector(".infected-count"); infectedCount.innerHTML = filesScanned.infected; } });

    Код выше будет приводить в движение счётчик сканированных файлов от 0 до 1 000 и счётчик заражённых файлов от 0 до 8. Помните, что вы можете анимировать числовые значения только таким образом. При попытке анимировать ключ из AAA в BOY будет выведено сообщение об ошибке.

    Кроме того, в коде использовалась функция обратного вызова ключа update , который вызывается на каждый кадр во время выполнения анимации. Здесь она использовалась для обновления количества сканированных и заражённых файлов. Однако вы можете пойти дальше и показать пользователям сообщение об ошибке, когда количество заражённых файлов превысит определённый порог.

    Массив: возможность указывать массив JavaScript в качестве значения targets будет полезна, если вам нужно анимировать множество элементов, которые относятся к разным категориям. Например, если вы хотите анимировать DOM-узел, объект и множество других элементов, основанных на CSS-селекторах, то можно это сделать, поместив их в массив, а затем определить массив в качестве значения для targets . Пример ниже должен прояснить ситуацию.

    Var multipleAnimations = anime({ targets: , translateY: 250 });

    Какие свойства можно анимировать с помощью Anime.js

    Теперь вы знаете, как определить разные элементы, которые нужно анимировать. Пришло время узнать, какие свойства и атрибуты могут быть анимированы при использовании библиотеки.

    Свойства CSS

    К таким, например, относятся ширина, высота и цвет для разных целевых элементов. Финальные значения разных анимируемых свойств вроде background-color определяются с использованием lowerCamelCase. Таким образом background-color превращается в backgroundColor . Код ниже иллюстрирует анимацию положения объекта left и цвета фона (backgroundColor) целевого объекта.

    Var animateLeft = anime({ targets: ".square", left: "50%" }); var animateBackground = anime({ targets: ".square", backgroundColor: "#f96" });

    Свойства могут принимать разные виды значений, которые они бы приняли при использовании обычного CSS. Например, свойство left может иметь такие значения: 50vh , 500px или 25em . Вы также можете не указывать единицу измерения после числа, но в таком случае ею станет px по умолчанию. Аналогичные действия можно выполнить с background-color , указав цвет в виде шестнадцатеричного значения или при помощи кода RGB или HSL.

    CSS-трансформирование

    Преобразование по осям X и Y достигается с помощью свойств translateX и translateY . Аналогичным образом можно масштабировать, наклонять или вращать элемент вдоль определённой оси, используя свойства: scale (масштабирование), skew (наклон) или rotate (поворот), соответствующие этой конкретной оси.

    Существует возможность определения разных углов или в градусах, или с помощью свойства turn . Значение turn, равное 1, соответствует 360 градусам. Это позволяет сделать вычисления проще, так как вы знаете, на сколько нужно повернуть элементы относительно своей оси. В примере ниже показано, как происходит анимация масштабирования, перехода или поворота как единичного свойства, так и всех сразу.

    Var animateScaling = anime({ targets: ".square", scale: 0.8 }); var animateTranslation = anime({ targets: ".square", translateX: window.innerWidth*0.8 }); var animateRotation = anime({ targets: ".square", rotate: "1turn" }); var animateAll = anime({ targets: ".square", scale: 0.8, translateX: window.innerWidth*0.8, rotate: "1turn" });

    Атрибуты SVG

    Единственное условие заключается в том, что значение атрибутов должно быть числовым. Способность анимировать разные атрибуты открывает возможности для создания некоторых классных эффектов. Поскольку эта статья ознакомительная, в ней будут приведены простые примеры.

    По мере углубления в библиотеку вы будете узнавать, как создаются более сложные анимации. Ниже представлен код для анимации атрибутов круга cy , cx и stroke-width . Как и с другими свойствами CSS, для stroke-width надо использовать CamelCase, чтобы код работал корректно.

    Var animateX = anime({ targets: ".circle", cx: window.innerWidth*0.6 }); var animateStrokeWidth = anime({ targets: ".circle", strokeWidth: "25" });

    Атрибуты DOM

    Можно анимировать числовые атрибуты DOM, подобно тому, как вы анимировали атрибуты SVG. Это может быть полезным для работы с элементом progress в HTML5 . У него есть два атрибута: value и max . В примере ниже будет выполняться анимация атрибута value , чтобы продемонстрировать прогресс перемещения файла на жёсткий диск.

    Var animateProgress = anime({ targets: "progress", value: 100, easing: "linear" });

    Заключение

    Вы познакомились со всеми вариантами выбора элементов в Anime.js, а также узнали, как анимировать разные свойства CSS и атрибуты, связанные с ними.

    В следующей статье вы узнаете, как контролировать плавность, задержку и длительность анимации как для единичных свойств, так и для группы. Затем вы научитесь контролировать все эти параметры для каждого отдельного элемента.

    Учитесь создавать HTML-анимации с помощью JavaScript.

    Базовый веб-страницы

    Чтобы продемонстрировать, как создавать HTML-анимации с JavaScript, мы будем использовать простой веб-страницы:

    Создание анимации контейнера

    Все анимации должны быть по отношению к элементу контейнера.

    Стиль Элементы

    Элемент контейнер должен быть создан с помощью стиля = "положение: относительное".

    Элемент анимации должен быть создан с помощью стиля = "позицию: абсолютная".

    пример

    #container {
    width: 400px;
    height: 400px;
    position: relative;
    background: yellow;
    }
    #animate {
    width: 50px;
    height: 50px;
    position: absolute;
    background: red;
    }

    Попробуй сам " Анимация Code

    анимации JavaScript выполняются путем программирования постепенные изменения стиля элемента.

    Изменения вызываются с помощью таймера. Когда интервал таймера мал, то анимация выглядит непрерывным.

    Основной код:

    пример

    function frame() {
    if (/* test for finished */) {
    clearInterval(id);
    } else {
    /* code to change the element style */
    }
    }

    Создание анимации с помощью JavaScriptпример

    Function myMove() {
    var elem = document.getElementById("animate");
    var pos = 0;
    var id = setInterval(frame, 5);
    function frame() {
    if (pos == 350) {
    clearInterval(id);
    } else {
    pos++;
    elem.style.top = pos + "px";
    elem.style.left = pos + "px";