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

bus*_*ted 24 animation webkit css3

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

我的问题是:无论何时启动第二个元素的动画,是否可以同步(两个元素同时达到它们的顶点等)动画跨两个元素?

这是我的HTML:

<div id="bouncy01">Drip</div>
<div id="bouncy02">droP</div>
Run Code Online (Sandbox Code Playgroud)

和我的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;
}
Run Code Online (Sandbox Code Playgroud)

最后,该问题的工作演示:http://jsfiddle.net/7ZLmq/2/

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

Val*_*rij 23

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

HTML:

<div id="bouncywrap">
    <div id="bouncy01">Drip</div>
    <div id="bouncy02">droP</div>
<div>
Run Code Online (Sandbox Code Playgroud)

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;
}
Run Code Online (Sandbox Code Playgroud)

演示http://jsfiddle.net/A92pU/1/

  • 就像这里http://jsfiddle.net/A92pU/2/,如果你提供更多细节/告诉我实际设计我可能会帮助更多 (4认同)
  • 为什么不?一个0px高,空,透明的div不会伤害设计和可用性. (2认同)

Kai*_*ido 18

Web动画 API现在允许非常精确且轻松地控制动画。

声明 Web 动画的方法有多种,但由于我们从 CSS 开始,因此以下是如何挂钩它:

// when the animation starts
document.querySelector("#bouncy02")
  .addEventListener("animationstart", (evt) => {
  // double check it the animation we wanted
  if (evt.animationName === "bounce") {
    // retrieve both Animation objects
    const myAnim = findAnimByName(evt.target, "bounce");
    const otherAnim = findAnimByName(document.querySelector("#bouncy01"), "bounce");
    // update mine to act as if it started
    // at the same time as the first one
    myAnim.startTime = otherAnim.startTime;
  }
});
// simple helper to find an Animation by animationName
function findAnimByName(elem, name) {
  // get all the active animations on this element
  const anims = elem.getAnimations();
  // return the first one with the expected animationName
  return anims.find((anim) => anim.animationName === name);
}
Run Code Online (Sandbox Code Playgroud)
@keyframes bounce {
    0% {transform: translateY(0px);}
    25% {transform: translateY(-2px);}
    50% {transform: translateY(-4px);}
    75% {transform: translateY(-2px);}
    100% {transform: translateY(0px);}
}
#bouncy01,
#bouncy02 {
    margin:10px;
    float: left;
    background: #ff0000;
    padding: 10px;
    border: 1px solid #777;
}
#bouncy01 {
    animation:bounce 0.25s ease-in-out infinite alternate;
}
#bouncy02 {
    background: #ffff00;
}
#bouncy02:hover {
    animation:bounce 0.25s ease-in-out infinite alternate;
}
Run Code Online (Sandbox Code Playgroud)
<div id="bouncy01">Drip</div>
<div id="bouncy02">droP</div>
Run Code Online (Sandbox Code Playgroud)

请注意,虽然令人惊讶的是它还没有那么普及,但这个 API 实际上已经存在了一段时间,而且它的浏览器支持(除了 IE 之外的所有浏览器)都非常好。

请注意,如果您不需要第一个动画“从头开始”开始,并且需要处理 2 个以上的元素,我们甚至可以通过使用常量值来进一步简化此代码,而不是startTime从运行中检索该值动画片:

// when the animation starts
document.querySelectorAll("div[id]").forEach((elem) => {
  elem.addEventListener("animationstart", (evt) => {
    // double check it the animation we wanted
    if (evt.animationName === "bounce") {
      const myAnim = findAnimByName(evt.target, "bounce");
      myAnim.startTime = 0; // same origin for all animations
    }
   });
});
// simple helper to find an Animation by animationName
function findAnimByName(elem, name) {
  // get all the active animations on this element
  const anims = elem.getAnimations();
  // return the first one with the expected animationName
  return anims.find((anim) => anim.animationName === name);
}
Run Code Online (Sandbox Code Playgroud)
@keyframes bounce {
    0% {transform: translateY(0px);}
    25% {transform: translateY(-2px);}
    50% {transform: translateY(-4px);}
    75% {transform: translateY(-2px);}
    100% {transform: translateY(0px);}
}
#bouncy01,
#bouncy02 {
    margin:10px;
    float: left;
    background: #ff0000;
    padding: 10px;
    border: 1px solid #777;
}
#bouncy01 {
    animation:bounce 0.25s ease-in-out infinite alternate;
}
#bouncy02 {
    background: #ffff00;
}
#bouncy02:hover {
    animation:bounce 0.25s ease-in-out infinite alternate;
}
Run Code Online (Sandbox Code Playgroud)
<div id="bouncy01">Drip</div>
<div id="bouncy02">droP</div>
Run Code Online (Sandbox Code Playgroud)


Mos*_*ian 8

我正在寻找这里提出的解决方案的替代解决方案,因为:

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

经过进一步研究,我发现了bealearts 的这个模块

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

import sync from 'css-animation-sync';
sync('spinner');
Run Code Online (Sandbox Code Playgroud)

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

信用:我使用Simurai 的这个小提琴的动画作为我的小提琴的基础。

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

window.addEventListener('animationstart', animationStart, true);
window.addEventListener('animationiteration', animationIteration, true);
Run Code Online (Sandbox Code Playgroud)

希望这有助于下一个人寻找解决此问题的方法。