CSS 悬停后如何在鼠标移开时反转动画

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16516793/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-29 22:50:40  来源:igfitidea点击:

How to reverse an animation on mouse out after hover

cssanimation

提问by Khaled

So, it is possible to have reverse animation on mouse out such as:

因此,可以在鼠标移开时使用反向动画,例如:

.class{
   transform: rotate(0deg);

}
.class:hover{
   transform: rotate(360deg);
}

but, when using @keyframes animation, I couldn't get it to work, e.g:

但是,当使用@keyframes 动画时,我无法让它工作,例如:

.class{
   animation-name: out;
   animation-duration:2s;

}
.class:hover{
   animation-name: in;
   animation-duration:5s;
   animation-iteration-count:infinite;

}
@keyframe in{
    to {transform: rotate(360deg);}
}

@keyframe out{
    to {transform: rotate(0deg);}
}

What is the optimal solution, knowing that I'd need iterations and animation itself?

知道我需要迭代和动画本身的最佳解决方案是什么?

http://jsfiddle.net/khalednabil/eWzBm/

http://jsfiddle.net/khalednabil/eWzBm/

回答by Xaltar

I think that if you have a to, you must use a from. I would think of something like :

我认为如果你有一个to,你必须使用一个from. 我会想到这样的事情:

@keyframe in {
    from: transform: rotate(0deg);
    to: transform: rotate(360deg);
}

@keyframe out {
    from: transform: rotate(360deg);
    to: transform: rotate(0deg);
}

Of course must have checked it already, but I found strange that you only use the transformproperty since CSS3 is not fully implemented everywhere. Maybe it would work better with the following considerations :

当然一定已经检查过了,但我发现奇怪的是你只使用了这个transform属性,因为 CSS3 没有在所有地方完全实现。考虑到以下因素,它可能会更好地工作:

  • Chrome uses @-webkit-keyframes, no particuliar version needed
  • Safari uses @-webkit-keyframessince version 5+
  • Firefox uses @keyframessince version 16 (v5-15 used @-moz-keyframes)
  • Opera uses @-webkit-keyframesversion 15-22 (only v12 used @-o-keyframes)
  • Internet Explorer uses @keyframessince version 10+
  • Chrome 使用@-webkit-keyframes,不需要特定版本
  • Safari@-webkit-keyframes从 5+ 版本开始使用
  • Firefox@keyframes从 16 版开始使用(使用了 v5-15 @-moz-keyframes
  • Opera 使用@-webkit-keyframes版本 15-22(仅使用 v12 @-o-keyframes
  • Internet Explorer@keyframes从版本 10+ 开始使用

EDIT :

编辑 :

I came up with that fiddle :

我想出了那个小提琴:

http://jsfiddle.net/JjHNG/35/

http://jsfiddle.net/JjHNG/35/

Using minimal code. Is it approaching what you were expecting ?

使用最少的代码。它是否接近您的预期?

回答by Giles Copp

I don't think this is achievable using only CSS animations. I am assuming that CSS transitions do notfulfil your use case, because (for example) you want to chain two animations together, use multiple stops, iterations, or in some other way exploit the additional power animations grant you.

我认为仅使用 CSS 动画是无法实现的。我假设 CSS 过渡不能满足您的用例,因为(例如)您想将两个动画链接在一起、使用多个停止、迭代或以其他方式利用额外的动画赋予您的能力。

I've not found any way to trigger a CSS animation specifically on mouse-out without using JavaScript to attach "over" and "out" classes. Although you can use the base CSS declaration trigger an animation when the :hover ends, that same animation will then run on page load. Using "over" and "out" classes you can split the definition into the base (load) declaration and the two animation-trigger declarations.

我没有找到任何方法可以在不使用 JavaScript 附加“over”和“out”类的情况下专门在鼠标移开时触发 CSS 动画。尽管您可以使用基本 CSS 声明在 :hover 结束时触发动画,但该动画将在页面加载时运行。使用“over”和“out”类,您可以将定义拆分为基本(加载)声明和两个动画触发器声明。

The CSS for this solution would be:

此解决方案的 CSS 将是:

.class {
    /* base element declaration */
}
.class.out {
   animation-name: out;
   animation-duration:2s;

}
.class.over {
   animation-name: in;
   animation-duration:5s;
   animation-iteration-count:infinite;
}
@keyframes in {
    from {
        transform: rotate(0deg);
    }
    to {
        transform: rotate(360deg);
    }
}
@keyframes out {
    from {
        transform: rotate(360deg);
    }
    to {
        transform: rotate(0deg);
    }
}

And using JavaScript (jQuery syntax) to bind the classes to the events:

并使用 JavaScript(jQuery 语法)将类绑定到事件:

$(".class").hover(
    function () {
        $(this).removeClass('out').addClass('over');
    },
    function () {
        $(this).removeClass('over').addClass('out');
    }
);

回答by Jordan Lafland

Its much easier than all this: Simply transition the same property on your element

它比这一切要容易得多:只需在您的元素上转换相同的属性

.earth { width:  0.92%;    transition: width 1s;  }
.earth:hover { width: 50%; transition: width 1s;  }

https://codepen.io/lafland/pen/MoEaoG

https://codepen.io/lafland/pen/MoEaoG

回答by ctf0

creating a reversed animation is kinda an overkill to a simple problem, what u need is

创建一个反向动画对于一个简单的问题来说有点矫枉过正,你需要的是

animation-direction: reverse

however this wont work on its own because animation spec is so dump that they forgot to add a way to restart the animation so here is how you do it with the help of js

但是这不会单独工作,因为动画规范太垃圾了以至于他们忘记添加重新启动动画的方法所以这里是你如何在 js 的帮助下做到这一点

let item = document.querySelector('.item')

// play normal
item.addEventListener('mouseover', () => {
  item.classList.add('active')
})

// play in reverse
item.addEventListener('mouseout', () => {
  item.style.opacity = 0 // avoid showing the init style while switching the 'active' class

  item.classList.add('in-active')
  item.classList.remove('active')

  // force dom update
  setTimeout(() => {
    item.classList.add('active')
    item.style.opacity = ''
  }, 5)

  item.addEventListener('animationend', onanimationend)
})

function onanimationend() {
  item.classList.remove('active', 'in-active')
  item.removeEventListener('animationend', onanimationend)
}
@keyframes spin {
  0% {
    transform: rotateY(0deg);
  }
  100% {
    transform: rotateY(180deg);
  }
}

div {
  background: black;
  padding: 1rem;
  display: inline-block;
}

.item {
  /* because span cant be animated */
  display: block;
  color: yellow;
  font-size: 2rem;
}

.item.active {
  animation: spin 1s forwards;
  animation-timing-function: ease-in-out;
}

.item.in-active {
  animation-direction: reverse;
}
<div>
  <span class="item">ABC</span>
</div>

回答by Andrew Lazarus

Would you be better off having just the one animation, but having it reverse?

你最好只有一个动画,但让它反转吗?

animation-direction: reverse

回答by Shishir Arora

we can use requestAnimationFrame to reset animation and reverse it when browser paints in next frame.

我们可以使用 requestAnimationFrame 来重置动画并在浏览器在下一帧中绘制时反转动画。

Also use onmouseenter and onmouseout event handlers to reverse animation direction

还可以使用 onmouseenter 和 onmouseout 事件处理程序来反转动画方向

As per

按照

Any rAFs queued in your event handlers will be executed in the ?same frame?. Any rAFs queued in a rAF will be executed in the next frame?.

在您的事件处理程序中排队的任何 rAF 都将在“同一帧”中执行。在 rAF 中排队的任何 rAF 将在下一帧中执行吗?。

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)"  
     ></div>

回答by Razvan_TK9692

Have tried several solutions here, nothing worked flawlessly; then Searched the web a bit more, to find GSAPat https://greensock.com/(subject to license, but it's pretty permissive); once you reference the lib ...

在这里尝试了多种解决方案,没有任何方法可以完美运行;然后在网上搜索了更多,在https://greensock.com/找到GSAP(需要许可,但非常宽松);一旦你引用了 lib ...

 <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.2.4/gsap.min.js"></script>

... you can go:

... 你可以走了:

  var el = document.getElementById('divID');    

  // create a timeline for this element in paused state
  var tl = new TimelineMax({paused: true});

  // create your tween of the timeline in a variable
  tl
  .set(el,{willChange:"transform"})
  .to(el, 1, {transform:"rotate(60deg)", ease:Power1.easeInOut});

  // store the tween timeline in the javascript DOM node
  el.animation = tl;

  //create the event handler
  $(el).on("mouseenter",function(){
    //this.style.willChange = 'transform';
    this.animation.play();
  }).on("mouseleave",function(){
     //this.style.willChange = 'auto';
    this.animation.reverse();
  });

And it will work flawlessly.

它会完美地工作。

回答by Ansipants

Try this:

尝试这个:

@keyframe in {
from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
}
@keyframe out {
from {
    transform: rotate(360deg);
  }
  to {
    transform: rotate(0deg);
  }
}

supported in Firefox 5+, IE 10+, Chrome, Safari 4+, Opera 12+

支持 Firefox 5+、IE 10+、Chrome、Safari 4+、Opera 12+