如何播放反向关键帧动画以便悬停?

pas*_*tgt 2 css hover css3 css-transitions css-animations

我正在尝试构建一个下拉菜单,首先下拉菜单向下滑动,然后从底部出现一个一个菜单项.在悬停时,它看起来不错,但我不知道如何在悬停时顺利播放.我要做的是先隐藏第二个子菜单项,然后隐藏第一个子菜单项,然后下拉滑动.

我尝试的是默认情况下将隐藏动画关键帧添加到下拉列表中,并在悬停时添加显示动画,延迟为0.但它看起来不能正常工作.(它也会在页面加载时生成动画,这对我不利)

ul li ul {
  -webkit-animation: hideDropdown 1s;
  -webkit-animation-delay: 0.5s;
}

ul li:hover ul {
  -webkit-animation: showDropdown 1s forwards;
  -webkit-animation-delay: 0s;
}
Run Code Online (Sandbox Code Playgroud)

小提琴演示(使用SCSS)

Har*_*rry 8

正如我在评论中指出的那样,产生动画的反向效果总是很复杂.这不是不可能,只是它需要额外的编码(如额外的关键帧)和调整所有相关的属性,以达到完美的效果.

transition如果还需要实现相反的效果,使用是最佳选择.完全可能产生使用过渡后的效果,它与动画制作方式非常相似.在:hover选择器,应用该transition设定,使得:first-child具有比所述第二(和随后的儿童)低级延迟,使得其首先出现和在默认选择应用transition设置,使得:first-child具有比其余部分更高的延迟.

使用转换还可以避免在页面加载本身上显示动画.这是因为只有当状态从一个状态变为另一个状态时才会发生转换.

body {
  background: #f1f1f1;
}

ul {
  height: 100px;
  position: relative;
  background: #fff;
}
ul li {
  display: block;
  float: left;
  margin: 0;
  list-style-type: none;
  padding: 0;
}
ul li a {
  display: block;
  height: 100px;
  line-height: 100px;
  padding: 0 20px;
}
ul li ul {
  position: absolute;
  left: 0px;
  right: 0px;
  top: 100px;
  height: 0px;
  opacity: 0;
  visibility: hidden;
  transition: all 1s 0.5s;
}
ul li ul li {
  position: absolute;
  left: 50px;
  bottom: 0px;
  width: 200px;
  overflow: hidden;
  height: 100px;
}
ul li ul li a {
  display: block;
  height: 100px;
  background: red;
  padding: 0 20px;
  position: absolute;
  opacity: 0;
  transform: translate(0px, 100px);
  transition: all 1s 0.2s;
}
ul li ul li:first-child a {
  transition-delay: 0.4s;
}
ul li ul li:last-child {
  left: 250px;
}
ul li ul li:last-child a {
  transition-delay: 0.2s;
}
ul li:hover ul {
  height: 100px;
  opacity: 1;
  visibility: visible;
  transition: all 1s 0s;
}
ul li:hover ul li a {
  opacity: 1;
  transform: translate(0px, 0px);
  transition: all 1s 0.2s;
}
ul li:hover ul li:last-child a {
  transition-delay: 0.4s;
}
Run Code Online (Sandbox Code Playgroud)
<ul>
  <li>
    <a href="#">Dropdown</a>
    <ul>
      <li><a href="">First</a></li>
      <li><a href="">second</a></li>
    </ul>
  </li>
  <li><a href="">Not dropdown</a></li>
</ul>
Run Code Online (Sandbox Code Playgroud)

注意:在上面的代码片段中,我使用了已编译的CSS并删除了所有-webkit-前缀,以使其在所有浏览器中都可以查看.如果您希望SCSS代码带有前缀,可以在此处找到它.


总而言之,我仍然想解释一下你的animation演示中出现了什么问题.你做了很多正确的工作,你几乎接近实现你想要的.

动画的工作方式是,一旦应用动画的选择器不再适用,动画就会被删除(丢失),并且元素会立即快速恢复到默认或原始状态.即使在悬停时应用了另一个动画,在反向动画的关键帧设置中指定的属性也不会应用,直到它们的延迟时间结束.这意味着ul并且a回弹到不可见(通过opacityvisibility)设置,在动画开始时(通过from关键帧)再次可见,然后动画到结束状态(再次通过to关键帧不可见).

此问题的解决方案是设置animation-fill-mode: backwardsula(未覆盖状态).此设置意味着from即使在延迟期间,元素也会获取关键帧中指定的属性.

body {
  background: #f1f1f1;
}
ul {
  height: 100px;
  position: relative;
  background: #fff;
}
ul li {
  display: block;
  float: left;
  margin: 0;
  list-style-type: none;
  padding: 0;
}
ul li a {
  display: block;
  height: 100px;
  line-height: 100px;
  padding: 0 20px;
}
ul li ul {
  position: absolute;
  left: 0px;
  right: 0px;
  top: 100px;
  height: 0px;
  visibility: hidden;
  animation: hideDropdown 1s;
  animation-delay: 0.5s;
  animation-fill-mode: backwards;
}
ul li ul li {
  position: absolute;
  left: 50px;
  bottom: 0px;
  width: 200px;
  overflow: hidden;
  height: 100px;
}
ul li ul li a {
  display: block;
  height: 100px;
  background: red;
  padding: 0 20px;
  position: absolute;
  opacity: 0;
  transform: translate(0px, 100px);
  animation: hideDropdownItem 1s 0.2s;
  animation-fill-mode: backwards;
}
ul li ul li:first-child a {
  animation-delay: 0.4s;
}
ul li ul li:last-child {
  left: 250px;
}
ul li ul li:last-child a {
  animation-delay: 0.2s;
}
ul li:hover ul {
  animation: showDropdown 1s forwards;
  animation-delay: 0s;
}
ul li:hover ul li a {
  animation: showDropdownItem 1s forwards 0.2s;
}
ul li:hover ul li:last-child a {
  animation-delay: 0.4s;
}
@keyframes showDropdown {
  from {
    opacity: 0;
    height: 0;
    visibility: hidden;
  }
  to {
    height: 100px;
    opacity: 1;
    visibility: visible;
  }
}
@keyframes hideDropdown {
  from {
    height: 100px;
    opacity: 1;
    visibility: visible;
  }
  to {
    opacity: 0;
    height: 0;
    visibility: hidden;
  }
}
@keyframes showDropdownItem {
  from {
    opacity: 0;
    transform: translate(0px, 100px);
  }
  to {
    opacity: 1;
    transform: translate(0px, 0px);
  }
}
@keyframes hideDropdownItem {
  from {
    opacity: 1;
    transform: translate(0px, 0px);
  }
  to {
    opacity: 0;
    transform: translate(0px, 100px);
  }
}
Run Code Online (Sandbox Code Playgroud)
<ul>
  <li>
    <a href="#">Dropdown</a>
    <ul>
      <li><a href="">First</a>
      </li>
      <li><a href="">second</a>
      </li>
    </ul>
  </li>
  <li><a href="">Not dropdown</a>
  </li>
</ul>
Run Code Online (Sandbox Code Playgroud)

注意:与第一个代码段相同,上面的代码也使用没有前缀的纯CSS.这里提供带前缀的SCSS版本.

但如前所述,这不会阻止动画在页面加载时可见.阻止它的唯一方法是使用JavaScript.