Cómo revertir una animación al sacar el mouse después de pasar el mouse

91

Por lo tanto, es posible tener una animación inversa con el mouse, como:

.class{
   transform: rotate(0deg);

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

pero, al usar la animación @keyframes, no pude hacer que funcione, por ejemplo:

.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);}
}

¿Cuál es la solución óptima, sabiendo que necesitaría iteraciones y animación en sí?

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

Khaled
fuente
¿No sería mejor usar transiciones, como aquí, jsfiddle.net/HQFby ?
piatek
La respuesta ya está publicada en stackoverflow. ingrese la descripción del enlace aquí
agua

Respuestas:

61

Creo que si tienes un to, debes usar un from. Pensaría en algo como:

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

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

Por supuesto, ya debe haberlo verificado, pero me pareció extraño que solo use la transformpropiedad ya que CSS3 no está completamente implementado en todas partes. Quizás funcionaría mejor con las siguientes consideraciones:

  • Usos de Chrome @-webkit-keyframes, no se necesita una versión particular
  • Safari utiliza @-webkit-keyframesdesde la versión 5+
  • Firefox usa @keyframesdesde la versión 16 (se usa v5-15 @-moz-keyframes)
  • Opera usa la @-webkit-keyframesversión 15-22 (solo se usa la v12 @-o-keyframes)
  • Internet Explorer utiliza @keyframesdesde la versión 10+

EDITAR:

Se me ocurrió ese violín:

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

Usando código mínimo. ¿Se acerca a lo que esperabas?

Xaltar
fuente
1
IE 10 admite animaciones de fotogramas clave.
dlev
4
Eso revierte la transición, pero el problema es que si el mouse está fuera antes del final de la transición de desplazamiento, obtenemos este "salto". Después de algunas búsquedas, aparentemente el estado del elemento debe ser "persistente" para que podamos revertir desde la posición de rotación final, para ese "modo de relleno de animación: adelante; se puede utilizar, pero no parece funcionar.
Khaled
22
@Xaltar Cuando carga la aplicación por primera vez, la primera animación se reproduce sin pasar el cursor sobre el cuadrado. ¿Hay alguna forma de evitar que ocurra la animación de carga inicial?
jlewkovich
3
¿Alguien encontró una solución para la primera animación que se reproduce por sí sola después de actualizar? Algo importante.
user2619824
2
Esta respuesta es en última instancia inútil si no puede suprimir la animación que se reproduce la primera vez
NearHuscarl
20

Es mucho más fácil que todo esto: simplemente transfiera la misma propiedad en su elemento

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

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

Jordan Lafland
fuente
4
Sí, pero esto solo funcionará si solo se cambia una propiedad.
Marcus
4
@Marcustransition: border-color 0.3s, background-color 0.3s, color 0.3s;
Scoots
4
Woah, CSS ha recorrido un largo camino desde la última vez que hice programación web: D
Franz D.
5
está preguntando por la animación !!
iKamy
18

No creo que esto se pueda lograr usando solo animaciones CSS. Supongo que las transiciones CSS no cumplen con su caso de uso, porque (por ejemplo) desea encadenar dos animaciones juntas, usar múltiples paradas, iteraciones o de alguna otra manera explotar la potencia adicional que le otorgan las animaciones.

No he encontrado ninguna forma de activar una animación CSS específicamente al sacar el mouse sin usar JavaScript para adjuntar clases "over" y "out". Aunque puede utilizar la declaración CSS base para activar una animación cuando finaliza: hover, esa misma animación se ejecutará al cargar la página. Usando las clases "over" y "out", puede dividir la definición en la declaración base (carga) y las dos declaraciones de activación de animación.

El CSS para esta solución sería:

.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);
    }
}

Y usando JavaScript (sintaxis jQuery) para vincular las clases a los eventos:

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

Crear una animación inversa es un poco exagerado para un problema simple, lo que necesitas es

animation-direction: reverse

sin embargo, esto no funcionará por sí solo porque la especificación de la animación es tan volcada que se olvidaron de agregar una forma de reiniciar la animación, así que así es como se hace con la ayuda de 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>

ctf0
fuente
4

¿Sería mejor tener solo una animación, pero al revés?

animation-direction: reverse
Andrés Lázaro
fuente
4
Actualmente solo es compatible con algunos navegadores
Adam Hutchinson
¿Tienes algún ejemplo?
MD Ashik
3

podemos usar requestAnimationFrame para restablecer la animación e invertirla cuando el navegador pinta en el siguiente cuadro.

También use los controladores de eventos onmouseenter y onmouseout para invertir la dirección de la animación

Según

Cualquier rAF en cola en sus controladores de eventos se ejecutará en el mismo marco. Cualquier rAF en cola en un rAF se ejecutará en el siguiente cuadro.

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>

Shishir Arora
fuente
0

Prueba esto:

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

compatible con Firefox 5+, IE 10+, Chrome, Safari 4+, Opera 12+

Ansipantes
fuente
0

He probado varias soluciones aquí, nada funcionó perfectamente; luego busqué en la web un poco más, para encontrar GSAP en https://greensock.com/ (sujeto a licencia, pero es bastante permisivo); una vez que hace referencia a la lib ...

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

... se puede ir:

  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();
  });

Y funcionará a la perfección.

Razvan_TK9692
fuente