Come invertire un'animazione all'uscita del mouse dopo il passaggio del mouse


91

Quindi, è possibile avere un'animazione inversa all'uscita del mouse come:

.class{
   transform: rotate(0deg);

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

ma, quando si utilizza l'animazione @keyframes, non sono riuscito a farlo funzionare, ad esempio:

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

Qual è la soluzione ottimale, sapendo che avrei bisogno di iterazioni e animazione stessa?

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


Non sarebbe meglio usare le transizioni, come qui - jsfiddle.net/HQFby ?
piatek

La risposta è già stata pubblicata su stackoverflow. inserisci qui la descrizione del link
watereffect

Risposte:


61

Penso che se hai un to, devi usare un from. Penserei a qualcosa di simile:

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

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

Ovviamente deve averlo già verificato, ma ho trovato strano che usi solo la transformproprietà poiché CSS3 non è completamente implementato ovunque. Forse funzionerebbe meglio con le seguenti considerazioni:

  • Chrome utilizza @-webkit-keyframes, nessuna versione particolare necessaria
  • Safari utilizza @-webkit-keyframesdalla versione 5+
  • Firefox utilizza @keyframesdalla versione 16 (v5-15 utilizzata @-moz-keyframes)
  • Opera utilizza la @-webkit-keyframesversione 15-22 (utilizzata solo la v12 @-o-keyframes)
  • Internet Explorer utilizza @keyframesdalla versione 10+

MODIFICARE :

Ho inventato quel violino:

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

Utilizzando un codice minimo. Si sta avvicinando a quello che ti aspettavi?


1
IE 10 supporta le animazioni dei fotogrammi chiave.
dlev

4
Questo ripristina la transizione, ma il problema è che se il mouse è fuori prima della fine della transizione hover otteniamo questo "salto". Dopo alcune ricerche apparentemente lo stato dell'elemento deve essere "persistente" in modo che possiamo tornare dalla posizione di rotazione finale, per quella "modalità di riempimento animazione: avanti;" può essere utilizzato, ma non sembra funzionare.
Khaled

21
@Xaltar Quando carichi l'app per la prima volta, la prima animazione viene riprodotta senza passare il mouse sul quadrato. C'è comunque per fermare che si verifichi l'animazione di caricamento iniziale?
jlewkovich

2
Qualcuno ha trovato una soluzione alla prima animazione riprodotta da sola dopo l'aggiornamento? Un po 'importante.
user2619824

1
Questa risposta è in definitiva inutile se non è possibile sopprimere l'animazione riprodotta la prima volta
NearHuscarl

20

È molto più facile di tutto questo: trasferisci semplicemente la stessa proprietà sul tuo elemento

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

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


4
Sì, ma funzionerà solo se viene modificata solo una proprietà.
Marcus

4
@Marcustransition: border-color 0.3s, background-color 0.3s, color 0.3s;
Scoots

4
Woah, CSS ha fatto molta strada dall'ultima volta che ho fatto un po 'di programmazione web: D
Franz D.

5
chiede dell'animazione !!
iKamy

18

Non credo che ciò sia realizzabile utilizzando solo animazioni CSS. Presumo che le transizioni CSS non soddisfino il tuo caso d'uso, perché (ad esempio) vuoi concatenare due animazioni insieme, utilizzare più fermate, iterazioni o in qualche altro modo sfruttare la potenza aggiuntiva che le animazioni ti garantiscono.

Non ho trovato alcun modo per attivare un'animazione CSS specificamente al mouse-out senza utilizzare JavaScript per allegare classi "over" e "out". Sebbene sia possibile utilizzare la dichiarazione CSS di base per attivare un'animazione quando: hover termina, la stessa animazione verrà quindi eseguita al caricamento della pagina. Usando le classi "over" e "out" puoi dividere la definizione nella dichiarazione di base (load) e nelle due dichiarazioni di attivazione dell'animazione.

Il CSS per questa soluzione sarebbe:

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

E utilizzando JavaScript (sintassi jQuery) per associare le classi agli eventi:

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

8

creare un'animazione invertita è un po 'eccessivo per un semplice problema, ciò di cui hai bisogno è

animation-direction: reverse

tuttavia questo non funzionerà da solo perché le specifiche dell'animazione sono così stupide che si sono dimenticati di aggiungere un modo per riavviare l'animazione quindi ecco come lo fai con l'aiuto di 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>



3

possiamo usare requestAnimationFrame per ripristinare l'animazione e invertirla quando il browser dipinge nel frame successivo.

Utilizzare anche i gestori di eventi onmouseenter e onmouseout per invertire la direzione dell'animazione

Come da

Qualsiasi rAF accodato nei gestori di eventi verrà eseguito nello stesso frame. Qualsiasi rAF accodato in un rAF verrà eseguito nel frame successivo.

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>


0

Prova questo:

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

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


0

Ho provato diverse soluzioni qui, niente ha funzionato perfettamente; poi ho cercato un po 'di più sul web, per trovare GSAP su https://greensock.com/ (soggetto a licenza, ma è abbastanza permissivo); una volta fatto riferimento alla libreria ...

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

... Puoi andare:

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

E funzionerà perfettamente.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.