Comment inverser une animation à la souris après le survol

91

Ainsi, il est possible d'avoir une animation inversée à la souris comme:

.class{
   transform: rotate(0deg);

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

mais, lors de l'utilisation de l'animation @keyframes, je ne pouvais pas le faire fonctionner, par exemple:

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

Quelle est la solution optimale, sachant que j'aurais besoin d'itérations et d'animation elle-même?

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

Khaled
la source
Ne serait-il pas préférable d'utiliser des transitions, comme ici - jsfiddle.net/HQFby ?
piatek
La réponse est déjà publiée sur stackoverflow. entrez la description du lien ici
watereffect

Réponses:

61

Je pense que si vous avez un to, vous devez utiliser un from. Je penserais à quelque chose comme:

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

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

Bien sûr, il doit déjà l'avoir vérifié, mais j'ai trouvé étrange que vous n'utilisiez que la transformpropriété car CSS3 n'est pas entièrement implémenté partout. Peut-être que cela fonctionnerait mieux avec les considérations suivantes:

  • Chrome utilise @-webkit-keyframes, aucune version particulière nécessaire
  • Safari utilise @-webkit-keyframesdepuis la version 5+
  • Firefox utilise @keyframesdepuis la version 16 (v5-15 utilisée @-moz-keyframes)
  • Opera utilise la @-webkit-keyframesversion 15-22 (seule la v12 est utilisée @-o-keyframes)
  • Internet Explorer utilise @keyframesdepuis la version 10+

ÉDITER :

Je suis venu avec ce violon:

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

Utilisation de code minimal. Est-il proche de ce que vous attendiez?

Xaltar
la source
1
IE 10 prend en charge les animations d'images clés.
dlev
4
Cela annule la transition, mais le problème est que si la souris est sortie avant la fin de la transition de survol, nous obtenons ce "saut". Après quelques recherches apparemment, l'état de l'élément doit être "persistant" afin que nous puissions revenir de la position de rotation finale, pour ce "mode de remplissage d'animation: en avant;" peut être utilisé, mais cela ne semble pas fonctionner.
Khaled
21
@Xaltar Lorsque vous chargez l'application pour la première fois, la première animation est lue sans survoler le carré. Est-il possible d'arrêter cette animation de chargement initiale?
jlewkovich
2
Quelqu'un a-t-il trouvé une solution pour que la première animation soit lue seule après avoir été rafraîchie? Assez important.
user2619824
1
Cette réponse est finalement inutile si vous ne pouvez pas supprimer l'animation en cours de lecture pour la première fois
NearHuscarl
20

C'est beaucoup plus facile que tout cela: il suffit de transférer la même propriété sur votre élément

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

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

Jordan Lafland
la source
4
Oui, mais cela ne fonctionnera que si une seule propriété est modifiée.
Marcus
4
@Marcustransition: border-color 0.3s, background-color 0.3s, color 0.3s;
Scoots
4
Woah, CSS a parcouru un long chemin depuis la dernière fois que j'ai fait de la programmation Web: D
Franz D.
5
il pose des questions sur l'animation !!
iKamy
18

Je ne pense pas que cela soit réalisable en utilisant uniquement des animations CSS. Je suppose que les transitions CSS ne répondent pas à votre cas d'utilisation, car (par exemple) vous souhaitez enchaîner deux animations, utiliser plusieurs arrêts, itérations ou d'une autre manière exploiter les animations de puissance supplémentaires que vous accordez.

Je n'ai trouvé aucun moyen de déclencher une animation CSS spécifiquement au passage de la souris sans utiliser JavaScript pour attacher des classes «over» et «out». Bien que vous puissiez utiliser la déclaration CSS de base pour déclencher une animation lorsque le: hover se termine, cette même animation s'exécutera ensuite au chargement de la page. En utilisant les classes "over" et "out", vous pouvez diviser la définition en la déclaration de base (load) et les deux déclarations de déclenchement d'animation.

Le CSS pour cette solution serait:

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

Et en utilisant JavaScript (syntaxe jQuery) pour lier les classes aux événements:

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

créer une animation inversée est un peu exagéré pour un problème simple, ce dont vous avez besoin est

animation-direction: reverse

Cependant, cela ne fonctionnera pas tout seul car les spécifications d'animation sont tellement vides qu'ils ont oublié d'ajouter un moyen de redémarrer l'animation, alors voici comment procéder avec l'aide 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
la source
4

Seriez-vous mieux d'avoir une seule animation, mais l'inverser?

animation-direction: reverse
Andrew Lazarus
la source
4
Actuellement uniquement pris en charge dans certains navigateurs
Adam Hutchinson
Avez-vous un exemple?
MD Ashik
3

nous pouvons utiliser requestAnimationFrame pour réinitialiser l'animation et l'inverser lorsque le navigateur peint dans l'image suivante.

Utilisez également les gestionnaires d'événements onmouseenter et onmouseout pour inverser la direction de l'animation

Selon

Tous les rAF mis en file d'attente dans vos gestionnaires d'événements seront exécutés dans le même cadre. Tous les rAF mis en file d'attente dans un rAF seront exécutés dans la trame suivante.

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
la source
0

Essaye ça:

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

pris en charge dans Firefox 5+, IE 10+, Chrome, Safari 4+, Opera 12+

Ansipants
la source
0

J'ai essayé plusieurs solutions ici, rien n'a fonctionné parfaitement; puis j'ai cherché un peu plus sur le Web, pour trouver GSAP à https://greensock.com/ (sous réserve de licence, mais c'est assez permissif); une fois que vous faites référence à la lib ...

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

... tu peux y aller:

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

Et cela fonctionnera parfaitement.

Razvan_TK9692
la source