Как синхронизировать анимацию CSS через несколько элементов?

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

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

Здесь мой HTML:

<div id="bouncy01">Drip</div>
<div id="bouncy02">droP</div>

и мой CSS:

@-webkit-keyframes bounce {
    0% {-webkit-transform: translateY(0px);}
    25% {-webkit-transform: translateY(-2px);}
    50% {-webkit-transform: translateY(-4px);}
    75% {-webkit-transform: translateY(-2px);}
    100% {-webkit-transform: translateY(0px);}
}
#bouncy01,
#bouncy02 {
    margin:10px;
    float: left;
    background: #ff0000;
    padding: 10px;
    border: 1px solid #777;
}
#bouncy01 {
    -webkit-animation:bounce 0.25s ease-in-out infinite alternate;
}
#bouncy02 {
    background: #ffff00;
}
#bouncy02:hover {
    -webkit-animation:bounce 0.25s ease-in-out infinite alternate;
}

и, наконец, рабочая демонстрация проблемы: http://jsfiddle.net/7ZLmq/2/

(чтобы увидеть проблему, наведите указатель мыши на желтый блок)

Ответы

Ответ 1

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

HTML:

<div id="bouncywrap">
    <div id="bouncy01">Drip</div>
    <div id="bouncy02">droP</div>
<div>

CSS

@-webkit-keyframes bounce {
    0% { padding-top:1px;}
/* using padding as it does not affect position:relative of sublinks
 * using 0 instead of 0 b/c of a box-model issue,
 * on kids wiht margin, but parents without margin, just try out
 */
    50% { padding-top:5px;} /*desired value +1*/
    100% { padding-top:1px;}
}

#bouncy01,
#bouncy02 {
    margin:10px;
    background: #ff0000;
    padding: 10px;
    border: 1px solid #777;
    width:30px;
       position:absolute;
}
#bouncywrap {
    -webkit-animation:bounce 0.125s ease-in-out infinite;
    position:relative;
    width:140px;
    height:50px;
/*    background:grey; /*debug*/
}
#bouncy02 {
    background: #ffff00;
    left:60px;
    top:2px; /*half of desired value, just a fix for the optic*/
}
#bouncy02:hover {
    position:relative; /*here happens the magic*/
    top:0px;
}

demo http://jsfiddle.net/A92pU/1/

Ответ 2

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

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

Я немного изменил ваш код, чтобы получить this.

Ответ 3

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

В разделе "Манипулирование CSS-анимациями" читайте информацию о состоянии сохранения состояния здесь; читайте об отрицательной задержке, чтобы искать здесь.

Ответ 4

при наведении мыши:

  1. удалить классы анимации из обоих элементов
  2. используйте requestAnimationFrame(() => { ... add here "bounce" class to both elements })

Должен синхронизироваться красиво.

Ответ 5

Я искал альтернативное решение, предложенное здесь, потому что:

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

После дальнейших исследований я обнаружил этот модуль от bealearts.

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

import sync from 'css-animation-sync';
sync('spinner');

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

Предоставлено: я использовал анимацию из этой скрипки Симурая в качестве основы для моей скрипки.

Если кто-то хочет воспроизвести механизм, лежащий в основе этой синхронизации, код открыт, но по сути он использует прослушиватели событий для самой анимации в качестве точек синхронизации:

window.addEventListener('animationstart', animationStart, true);
window.addEventListener('animationiteration', animationIteration, true);

Надеюсь, что это поможет следующему человеку, ищущему решение этой проблемы.