Динамически создавать и применять анимацию CSS3

Функция .animate() в jQuery не позволяет анимировать все свойства CSS3, которые можно анимировать (например, background-color). Есть ли хороший стандартный способ динамического создания, применения и удаления анимации CSS3 к элементам на странице?

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


person dlkulp    schedule 03.02.2016    source источник
comment
Взгляните на bounce.js   -  person bumpy    schedule 03.02.2016
comment
Здесь не упоминается цвет фона или другие вещи, которые jquery еще не может сделать. Мне что-то не хватает или bounce.js - это другая реализация jquery.animate ()?   -  person dlkulp    schedule 03.02.2016
comment
Можете ли вы просто использовать addClass и removeClass и установить анимацию в своем CSS?   -  person Steve K    schedule 03.02.2016
comment
Сами анимации должны быть динамичными.   -  person dlkulp    schedule 03.02.2016


Ответы (1)


Да, мы можем динамически создавать, применять и удалять анимацию CSS3 для элемента на странице.

Чтобы динамически создавать анимацию, нам нужно использовать функции insertRule или addRule, чтобы добавить @keyframes правила и добавить их в таблицу стилей. После добавления анимации применить ее к элементу очень просто, нам просто нужно установить необходимое значение свойства для свойства animation с помощью встроенных стилей. Удалить его очень просто, нам просто нужно вернуть значение null, когда его нужно удалить.

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

Нет других более простых способов динамического создания анимации CSS3. Все возможные решения будут включать создание и добавление @keyframes к таблицам стилей с использованием базовой insertRule, addRule или специальной функции appendRule для ключевых кадров (которая используется для добавления правил к существующему ключевому кадру).

var elm = document.querySelector('.to-animate');
var op = document.querySelector('.output');

var animName = "shake-up-down",
  animDuration = "3s",
  animTiming = "linear",
  animFillMode = "forwards",
  animIteration = "3";

var ruleText = "0% {transform: translateY(0px);}";
ruleText += "25% {transform: translateY(10px);}";
ruleText += "75% {transform: translateY(-10px);}";
ruleText += "100% {transform: translateY(0px);}";


/* From David Walsh's blog */
function addCSSAnimRule(sheet, name, rules, index) {
  if ("insertRule" in sheet) {
    sheet.insertRule("@keyframes " + name + "{" + rules + "}", index);
  } else if ("addRule" in sheet) {
    sheet.addRule("@keyframes " + name, rules, index);
  }
}

/* Self written */
function applyAnimation(elm, name, duration, timing, iteration, fillmode) {
  elm.style["animation"] = name + " " + duration + " " + timing + " " + iteration + " " + fillmode;
  
  /* or if you want to set them individually, comment the above line and uncomment this
  elm.style["animationName"] = name;
  elm.style["animationDuration"] = duration;
  elm.style["animationTimingFunction"] = timing;
  elm.style["animationIterationCount"] = iteration
  elm.style["animationFillMode"] = fillmode;*/
}

addCSSAnimRule(document.styleSheets[0], animName, ruleText, 0);
applyAnimation(elm, animName, animDuration, animTiming, animIteration, animFillMode);

/* to print output */

elm.addEventListener("animationstart", function(e) {
  op.textContent = "Animation " + e.animationName + " has started.";
  op.textContent += "\n\nElement's Outer HTML: \n";
  op.textContent += elm.outerHTML;
  op.textContent += "\n\n------------------------------------------------------------------------------";
});

elm.addEventListener("animationend", function(e) {
  elm.removeAttribute("style"); /* remove the animation */
  op.textContent += "\nAnimation " + e.animationName + " has ended.";
  op.textContent += "\n\nElement's Outer HTML: \n";
  op.textContent += elm.outerHTML;
  op.textContent += "\n\n------------------------------------------------------------------------------";
});
.to-animate {
  height: 100px;
  width: 100px;
  margin: 10px;
  border: 1px solid red;
}
<div class='to-animate'></div>
<pre class='output'></pre>


Этот метод можно использовать для динамического создания и использования анимации любого типа. Ниже фрагмент создает и добавляет background-color анимацию.

var elm = document.querySelector('.to-animate');
var op = document.querySelector('.output');

var animName = "bgColor",
  animDuration = "4s",
  animTiming = "linear",
  animFillMode = "forwards",
  animIteration = "3";

var ruleText = "0% {background-color: red;}";
ruleText += "25% {background-color: orange;}";
ruleText += "50% {background-color: yellow;}";
ruleText += "75% {background-color: pink;}";
ruleText += "100% {background-color: red;}";


/* From David Walsh's blog */
function addCSSAnimRule(sheet, name, rules, index) {
  if ("insertRule" in sheet) {
    sheet.insertRule("@keyframes " + name + "{" + rules + "}", index);
  } else if ("addRule" in sheet) {
    sheet.addRule("@keyframes " + name, rules, index);
  }
}

/* Self written */
function applyAnimation(elm, name, duration, timing, iteration, fillmode) {
  elm.style["animation"] = name + " " + duration + " " + timing + " " + iteration + " " + fillmode;

  /* or if you want to set them individually, comment the above line and uncomment this
  elm.style["animationName"] = name;
  elm.style["animationDuration"] = duration;
  elm.style["animationTimingFunction"] = timing;
  elm.style["animationIterationCount"] = iteration
  elm.style["animationFillMode"] = fillmode;*/
}

addCSSAnimRule(document.styleSheets[0], animName, ruleText, 0);
applyAnimation(elm, animName, animDuration, animTiming, animIteration, animFillMode);

/* to print output */

elm.addEventListener("animationstart", function(e) {
  op.textContent = "Animation " + e.animationName + " has started.";
  op.textContent += "\n\nElement's Outer HTML: \n";
  op.textContent += elm.outerHTML;
  op.textContent += "\n\n------------------------------------------------------------------------------";
});

elm.addEventListener("animationend", function(e) {
  elm.removeAttribute("style"); /* remove the animation */
  op.textContent += "\nAnimation " + e.animationName + " has ended.";
  op.textContent += "\n\nElement's Outer HTML: \n";
  op.textContent += elm.outerHTML;
  op.textContent += "\n\n------------------------------------------------------------------------------";
});
.to-animate {
  height: 100px;
  width: 100px;
  margin: 10px;
  background-color: red;
}
<div class='to-animate'></div>
<pre class='output'></pre>


Кроссбраузерная версия:

Здесь кроссбраузерная версия с поддержкой старых браузеров с использованием методов, предоставляемых бесплатной библиотекой Prefix. Это было протестировано в IE10 +, Edge, Chrome v50 (dev-m), Firefox v43, Opera v35. Тестирование версии с префиксом проводилось в Safari 5.1.7 на Win 10.

person Harry    schedule 06.02.2016
comment
Мне нравится этот. +1 Не хватает только кроссбраузерности. (Или, по крайней мере, префиксы поставщиков для браузеров с поддержкой CSS3.) Для этого вы можете использовать другой фрагмент Дэвида: обнаружить префикс поставщика < / а>. - person Bram Vanroy; 06.02.2016
comment
@BramVanroy: Большое спасибо. На самом деле я разрывался между тем, использовать ли сценарий Дэвида (или) использовать библиотеку, например, без префиксов, и позволить им узнать префикс, необходимый для браузера. Думаю, я пойду вторым путем, чтобы не раздувать код еще больше (но ваш комментарий определенно ценен). - person Harry; 06.02.2016
comment
Да, @BramVanroy, и он также предоставляет переменную (PrefiFree.prefix), которую мы можем использовать для получения префикса, применимого для браузера пользователя. - person Harry; 06.02.2016
comment
@BramVanroy: Это то, о чем я говорил. Использование открытых функций и переменных Prefix free. Протестировано и работает во всех браузерах (тестирование префиксов проводилось в более старой версии Safari). - person Harry; 06.02.2016