Jak odwrócić animację po wyjechaniu myszą po najechaniu kursorem

91

Możliwe jest więc odwrócenie animacji po wyjechaniu myszą, na przykład:

.class{
   transform: rotate(0deg);

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

ale używając animacji @keyframes nie mogłem jej uruchomić, np:

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

Jakie jest optymalne rozwiązanie, wiedząc, że będę potrzebował iteracji i samej animacji?

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

Khaled
źródło
Czy nie byłoby lepiej użyć przejść, jak tutaj - jsfiddle.net/HQFby ?
piątek
Odpowiedź jest już opublikowana na stackoverflow. wprowadź opis linku tutaj
watereffect

Odpowiedzi:

61

Myślę, że jeśli masz to, musisz użyć from. Pomyślałbym o czymś takim:

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

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

Oczywiście musiałem to już sprawdzić, ale wydało mi się dziwne, że używasz tylko tej transformwłaściwości, ponieważ CSS3 nie wszędzie jest w pełni zaimplementowany. Może działałoby lepiej, biorąc pod uwagę następujące kwestie:

  • Chrome używa @-webkit-keyframes, żadna szczególna wersja nie jest potrzebna
  • Safari używa @-webkit-keyframesod wersji 5+
  • Firefox używa @keyframesod wersji 16 (używana wersja 5-15 @-moz-keyframes)
  • Opera używa @-webkit-keyframeswersji 15-22 (używana tylko wersja 12 @-o-keyframes)
  • Internet Explorer używa @keyframesod wersji 10+

EDYTOWAĆ :

Wymyśliłem to skrzypce:

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

Używając minimalnego kodu. Czy zbliża się do tego, czego się spodziewałeś?

Xaltar
źródło
1
IE 10 obsługuje animacje klatek kluczowych.
dlev
4
To odwraca przejście, ale problem polega na tym, że jeśli mysz jest wyłączona przed zakończeniem przejścia po najechaniu kursorem, otrzymujemy ten „skok”. Po pewnych poszukiwaniach najwyraźniej stan elementu musi zostać "utrwalony", abyśmy mogli powrócić z pozycji końcowej obrotu, dla tego "animacji-wypełnienia-tryb: do przodu; " może być używany, ale wygląda na to, że nie działa.
Khaled
22
@Xaltar Po pierwszym załadowaniu aplikacji pierwsza animacja jest odtwarzana bez najeżdżania na kwadrat. Czy w ogóle istnieje możliwość zatrzymania tej animacji początkowego ładowania?
jlewkovich
3
Czy ktoś znalazł rozwiązanie na samodzielne odtwarzanie pierwszej animacji po odświeżeniu? Trochę ważne.
user2619824
2
Ta odpowiedź jest ostatecznie bezużyteczna, jeśli nie możesz powstrzymać animacji odtwarzanej po raz pierwszy
NearHuscarl
20

Jest to o wiele łatwiejsze niż to wszystko: po prostu przenieś tę samą właściwość na swój element

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

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

Jordan Lafland
źródło
4
Tak, ale zadziała to tylko wtedy, gdy zmieniona zostanie tylko jedna właściwość.
Marcus
4
@Marcustransition: border-color 0.3s, background-color 0.3s, color 0.3s;
scoots
4
Woah, CSS przeszedł długą drogę od czasu, gdy ostatnio programowałem w sieci: D
Franz D.
5
pyta o animację !!
iKamy
18

Nie sądzę, że jest to osiągalne przy użyciu tylko animacji CSS. Zakładam, że przejścia CSS nie spełniają twojego przypadku użycia, ponieważ (na przykład) chcesz połączyć ze sobą dwie animacje, użyć wielu zatrzymań, iteracji lub w inny sposób wykorzystać dodatkowe animacje, które dają ci.

Nie znalazłem żadnego sposobu na wywołanie animacji CSS specjalnie po wyjechaniu myszą bez użycia JavaScript do dołączania klas „over” i „out”. Chociaż możesz użyć podstawowej deklaracji CSS, która wyzwoli animację po zakończeniu: hover, ta sama animacja zostanie następnie uruchomiona podczas ładowania strony. Używając klas „over” i „out”, można podzielić definicję na deklarację podstawową (load) i dwie deklaracje wyzwalacza animacji.

CSS dla tego rozwiązania wyglądałoby tak:

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

I używając JavaScript (składnia jQuery) do powiązania klas ze zdarzeniami:

$(".class").hover(
    function () {
        $(this).removeClass('out').addClass('over');
    },
    function () {
        $(this).removeClass('over').addClass('out');
    }
);
Giles Copp
źródło
8

tworzenie odwróconej animacji to trochę przesada w stosunku do prostego problemu, którego potrzebujesz

animation-direction: reverse

jednak to nie zadziała samodzielnie, ponieważ specyfikacja animacji jest tak zrzucona, że ​​zapomnieli dodać sposób na ponowne uruchomienie animacji, więc oto jak to zrobić za pomocą 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
źródło
4

Czy lepiej byłoby mieć tylko jedną animację, ale odwrócić ją?

animation-direction: reverse
Andrew Lazarus
źródło
4
Obecnie obsługiwane tylko w niektórych przeglądarkach
Adam Hutchinson
Masz jakiś przykład?
MD Ashik
3

możemy użyć requestAnimationFrame, aby zresetować animację i odwrócić ją, gdy przeglądarka maluje w następnej klatce.

Aby odwrócić kierunek animacji, użyj również programów obsługi zdarzeń onmouseenter i onmouseout

Jak na

Wszelkie elementy RAF w kolejce do obsługi zdarzeń zostaną wykonane w tej samej ramce. Wszelkie RAF'y w kolejce do RAF zostaną wykonane w następnej klatce.

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
źródło
0

Spróbuj tego:

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

obsługiwane w przeglądarkach Firefox 5+, IE 10+, Chrome, Safari 4+, Opera 12+

Ansipants
źródło
0

Wypróbowałem tutaj kilka rozwiązań, nic nie działało bez zarzutu; następnie Przeszukałem nieco sieć, aby znaleźć GSAP na https://greensock.com/ (podlega licencji, ale jest dość liberalne); gdy odwołasz się do biblioteki ...

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

... możesz iść:

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

I będzie działać bez zarzutu.

Razvan_TK9692
źródło