如何跨多个元素同步CSS动画?

时间:2011-01-29 19:29:16

标签: animation webkit css3

我在页面上有两个元素,我想通过CSS制作动画(特别是-webkit-animation)。动画本身只是上下弹跳一个元素。一个元素总是显示和弹跳,另一个元素在鼠标悬停(悬停)之前不会动画。

我的问题是:无论第二个元素的动画何时开始,是否可以同步(两个元素同时达到顶点等)动画,而不管第二个元素的动画何时开始?

这是我的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/

(看到问题,鼠标悬停在黄色块上)

8 个答案:

答案 0 :(得分:21)

我不认为它本身可能,但你可以通过使用弹跳包装和一些位置改变来实际破解类似的功能

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/

答案 1 :(得分:2)

看起来你可以只堆叠两个黄色的并切换可见性:悬停在父元素上。

您需要动画始终在运行,否则您将遇到同步问题。

我稍微修改了你的代码以获得this.

答案 2 :(得分:2)

您可以使用setInterval来维护第一个动画的动画状态,并为其他动画提供负延迟,以便在鼠标悬停时寻找匹配的关键帧。

在“操纵CSS动画”部分阅读有关state-keeping-interval-thing here的内容;了解寻求here的负延迟。

答案 3 :(得分:1)

鼠标悬停:

  1. 从两个元素中删除动画类
  2. 使用requestAnimationFrame(() => { ... add here "bounce" class to both elements })
  3. 应该很好地同步。

答案 4 :(得分:1)

计算并添加延迟,然后再添加类:

class Engine {
  // Constructor, size defaults to 1
  constructor(size = 1) {
    // Sets size to size
    this.size = size;
  }
  // Method
  start() {
    for (let i = 0; i < this.size, i++) {
      alert('Brrr');
    }
  }
}
class Car {
  // Constructor
  constructor(name) {
    // Sets engine to a new engine
    this.engine = new Engine();
    // Sets name to name
    this.name = name;
  }
  // Method
  introduceTo(name) {
    alert(`Hey ${name}, here is my car ${this.name}.`);
  }
}

let myCar = new Car('Ferrari');
myCar.engine = new Engine(5);
myCar.introduceTo('bro');
myCar.engine.start();

https://codepen.io/s-flhti/pen/GRoVXZw

答案 5 :(得分:1)

这是我在同步不同元素和 pseudo-elements 的动画方面的小探索,多亏了上述想法,解决方案变得非常简单。我希望这个小代码对某人有所帮助。

window.addEventListener('animationstart', e =>
    e.animationName == 'rgb' && e.target.getAnimations({subtree: true}).forEach(e => e.startTime = 0), true)

答案 6 :(得分:0)

我正在寻找此处提出的替代方案,因为:

  1. 我正在设置背景颜色的动画-无法在接受的答案中使用定位魔术。
  2. 我想避免在我的应用中计算非常简单的动画。

经过进一步研究,我发现this modulebealearts的人。

它公开了一个非常简洁的API,使您可以通过引用动画的名称在整个应用中使动画保持同步:

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

由于这似乎有点难以置信,所以我在这个小提琴中测试了库(是一个短文件),很高兴报告it works(将鼠标悬停在第三张图片上,我很快同步到第二张图片的动画):)。

信用:我使用Simurai的this fiddle中的动画作为我的小提琴的基础。

如果有人想复制此同步背后的机制,则代码是开放的,但从本质上讲,它使用动画本身的事件侦听器作为同步点:

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

希望这可以帮助下一个寻找解决此问题的人。

答案 7 :(得分:0)

您可以在设置交替状态的根元素上设置一个类,然后使用计时器替换该类

CSS

.alt .bouncy {
   padding-top:5px !important;
}
.bouncy {
   padding-top: 1px;
   transition: padding-top ease 500ms;
}

HTML

<div class="container">
    <div class="bouncy">Drip</div>
    <div class="bouncy">droP</div>
<div>

JavaScript

$(function () {
  setInterval(() => $(".container").toggleClass("alt"), 1000)
})

通过这种方式,过渡和计时器可以执行css动画的工作,但由单个主开关(容器)控制。