即使您在中途停止悬停,如何强制动画完成然后反转以开始悬停?

Posted

技术标签:

【中文标题】即使您在中途停止悬停,如何强制动画完成然后反转以开始悬停?【英文标题】:How to force an animation to finish and then reverse to start on hover, even when you stop hovering mid way through? 【发布时间】:2021-04-29 07:13:52 【问题描述】:

我发现了这个我觉得非常有趣的代码笔,并试图在悬停时启动,然后保持打开状态,直到您停止悬停,然后它会反转并关闭。我的问题是,首先,它要么在悬停时做动画,然后在悬停时直接跳到开始。同样,当在动画中途离开悬停时,它只是跳回到起点。我试过“.box:hover and box:hover:after”但没有成功。任何帮助将不胜感激!

The Pen 免责声明,这不是我的笔,我发现它并认为它很酷。 感谢the creator

 *
      margin:0;
      padding:0;
    
    .container 
      background: #f0f0f0;
      box-sizing: border-box;
      display: flex;
      justify-content: center;
      align-items: center;
      width: 100vw;
      height: 100vh;
    
    .box 
      border-radius: 20px;
      width: 60px;
      height: 60px;
      background: #f0f0f0;
      box-shadow:  0 0 0 #cccccc,
                   0 0 0 #ffffff,
                    10px 10px 10px #cccccc inset,
                    -10px -10px 10px #ffffff inset;
      animation: anime 3s cubic-bezier(0.16, 1, 0.3, 1) 1s infinite alternate;
      /* animation-fill-mode: forwards; */
    

    @keyframes anime 
      0% 
        width: 60px;
        height: 60px;
        background: #f0f0f0;
        box-shadow:  0 0 0 #cccccc,
                     0 0 0 #ffffff,
                      10px 10px 10px #cccccc inset,
                      -10px -10px 10px #ffffff inset;
      
      25% 
        width: 60px;
        height: 60px;
        background: #f8f8f8;
        box-shadow:  10px 10px 10px #cccccc,
                     10px 10px 10px #ffffff,
                     0 0 0 #cccccc inset,
                     0 0 0 #ffffff inset;
      
      50% 
        width: 60px;
        height: 240px;
        background: #f8f8f8;
        box-shadow:  10px 10px 10px #cccccc,
                     10px 10px 10px #ffffff,
                     0 0 0 #cccccc inset,
                     0 0 0 #ffffff inset;
      
      100% 
        width: 480px;
        height: 240px;
        background: #fafafa;
        box-shadow:  40px 40px 40px #cccccc,
                     0 0 0 #ffffff,
                     0 0 0 #cccccc inset,
                     2px 2px 2px #ffffff inset;
      
<body>
    <div class="container">
      <div class="box"></div>
    </div>
</body>

【问题讨论】:

【参考方案1】:

我猜你的问题的答案应该是这样的

function fn(el, isEnter) 
  el.className = "";
   requestAnimationFrame(() => 
    requestAnimationFrame(() => 
        el.className = isEnter? "in": "out";
    );
  );  

.in
  animation: k 1s forwards;


.out
  animation: k 1s forwards;
  animation-direction: reverse;


@keyframes k

from transform: rotate(0deg);
to   transform: rotate(360deg);

<div style="width:100px; height:100px; background-color:red" 
    onmouseenter="fn(this, true)"
    onmouseleave="fn(this, false)"  
    />

【讨论】:

【参考方案2】:

阅读animation-play-state 并查看hidden snippet。 如果你把这两者结合起来,你就会得到你所需要的:

*
margin:0;
padding:0;

.container 
background: #f0f0f0;
box-sizing: border-box;
display: flex;
  justify-content: center;
  align-items: center;
  width: 100vw;
  height: 100vh;

.box 
border-radius: 20px;
  width: 60px;
  height: 60px;
  background: #f0f0f0;
  box-shadow:  0 0 0 #cccccc,
             0 0 0 #ffffff,
              10px 10px 10px #cccccc inset,
              -10px -10px 10px #ffffff inset;
  animation: anime 3s cubic-bezier(0.16, 1, 0.3, 1) 1s infinite alternate;
  animation-play-state: paused; /* added */
  /* animation-fill-mode: forwards; */

body:hover .container .box 
  animation-play-state: paused; /* added */

body .container .box:hover 
  animation-play-state: running; /* added */

@keyframes anime 
  0% 
    width: 60px;
    height: 60px;
    background: #f0f0f0;
    box-shadow:  0 0 0 #cccccc,
                 0 0 0 #ffffff,
                  10px 10px 10px #cccccc inset,
                  -10px -10px 10px #ffffff inset;
  
  25% 
    width: 60px;
    height: 60px;
    background: #f8f8f8;
    box-shadow:  10px 10px 10px #cccccc,
                 10px 10px 10px #ffffff,
                 0 0 0 #cccccc inset,
                 0 0 0 #ffffff inset;
  
  50% 
    width: 60px;
    height: 240px;
    background: #f8f8f8;
    box-shadow:  10px 10px 10px #cccccc,
                 10px 10px 10px #ffffff,
                 0 0 0 #cccccc inset,
                 0 0 0 #ffffff inset;
  
  100% 
    width: 480px;
    height: 240px;
    background: #fafafa;
    box-shadow:  40px 40px 40px #cccccc,
                 0 0 0 #ffffff,
                 0 0 0 #cccccc inset,
                 2px 2px 2px #ffffff inset;
  
<body>
  <div class="container">
    <div class="box"></div>
  </div>
</body>

最初,动画是暂停的。当 body 悬停但 box 没有悬停时,动画会暂停。当框悬停时,动画运行。我想这正是你所需要的。

【讨论】:

嗯,是的,也不是。我希望它在悬停时完成动画,但如果我停止悬停,它会将动画的反向平稳地返回到开始。

以上是关于即使您在中途停止悬停,如何强制动画完成然后反转以开始悬停?的主要内容,如果未能解决你的问题,请参考以下文章

如果动画在jQuery中停止,如何防止回调?

悬停时启动旋转动画,但悬停时仍会完成

JQuery Animate - 如何在悬停后立即停止悬停功能(不要完成悬停功能)

悬停时停止 CSS 动画

悬停时如何停止当前正在运行的动画并更改样式

退出悬停时反转动画