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
How to reverse an animation on mouse out after hover
提问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?
知道我需要迭代和动画本身的最佳解决方案是什么?
回答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 transform
property 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-keyframes
since version 5+ - Firefox uses
@keyframes
since version 16 (v5-15 used@-moz-keyframes
) - Opera uses
@-webkit-keyframes
version 15-22 (only v12 used@-o-keyframes
) - Internet Explorer uses
@keyframes
since 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 :
我想出了那个小提琴:
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; }
回答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 事件处理程序来反转动画方向
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+