How to Play an Animation on Hover and Pause When Hover Is Not Active

How to play an animation on hover and pause when hover is not active

Use animation instead of transition and make use of animation-play-stateMDN

button{
animation: rotate360 1.2s linear infinite; /* animation set */
animation-play-state: paused; /* ...but paused */
}
button:hover{
animation-play-state: running; /* Run on hover! */
}
@keyframes rotate360 {
to { transform: rotate(360deg); }
}
<button>X</button>

Play CSS animation on hover, pause on hover out

example jsfiddle

set the animation on #tech with play state paused

#tech {
-webkit-animation-play-state:paused;
-webkit-animation: moveSlideshow 10s linear infinite;
}

then change play-state to running on hover

#tech:hover{
-webkit-animation-play-state:running;
}

Pause a WebKit animation on hover

Instead of:

.quote:nth-child(1):hover 
{
-webkit-animation-play-state: paused;
-moz-animation-play-state: paused;
-o-animation-play-state: paused;
animation-play-state: paused;
}

use:

.quote-wrapper:hover .quote 
{
-webkit-animation-play-state: paused;
-moz-animation-play-state: paused;
-o-animation-play-state: paused;
animation-play-state: paused;
}

DEMO: http://jsfiddle.net/j4Abq/2/

CSS start and pause animation on hover

Oh, you are really close to it. Just need to add the keyframe for the 100% state as well.

.pers {  margin-bottom: -4px;  width: 300px;  height: 300px;  display: inline-block;  background-color: green;  clip-path: polygon(50% 52%, 100% 0, 100% 100%, 0% 100%);}
.pers:hover { animation: polygons 1s; animation-fill-mode: forwards;}
@keyframes polygons { 75%,100% { clip-path: polygon(0 0, 100% 0, 100% 100%, 0% 100%); }}
<div class="thisUs">      <div class="pers">    </div>

Keep item animated after unhover

You need some way of the element 'remembering' that it has to carry on rotating.

For that you'll need a bit of Javascript to sense when the mouse is hovering over the element and to sense when the transition has ended. These events will add and remove a class respectively.

const div = document.querySelector('.header .logo img');

function addRotate() {
div.classList.add('rotate');
}

function removeRotate() {
div.classList.remove('rotate');
}
div.addEventListener('mouseover', addRotate);
div.addEventListener('transitionend', removeRotate);
.header .logo img {
transform: rotate(0deg);
transition: transform 0s 0s;
}

.header .logo img.rotate {
transform: rotate(360deg);
transition: transform 1.2s;
}
<div class="header">
<div class="logo">
<img src="https://picsum.photos/id/1015/200/300">
</div>
</div>

css3 animation on :hover; force entire animation

I'm afraid that the only way to solve this is with a bit of javascript, you must add the animation as a class and then remove it when the animation finishes.

$(".box").bind("webkitAnimationEnd mozAnimationEnd animationend", function(){
$(this).removeClass("animated")
})

$(".box").hover(function(){
$(this).addClass("animated");
})

http://jsfiddle.net/u7vXT/

Animation not stopping on hover using webkit-animation-play-state

There is no way to achieve a one-time hover without JavaScript or jQuery:

CSS:

.one_time {
-webkit-animation-play-state: paused;
}

JavaScript:

function hoverOnce(target, type, listener) {
target.addEventListener(type, function fn(event) {
target.removeEventListener(type, fn);
listener(event);
});
};

hoverOnce(document.getElementById("myelement"), "mouseover", function (event) {
document.getElementById("myelement").className = "one_time";

});

jQuery:

$(".button-color-2").one("mouseenter", function(e){
$("#myelement").addClass("one_time");
});

How can I make Animation Play State paused to work in React on hover

The problem


1. There is a difference between transition and animation in CSS
concepts, between them, there is the definition of "pause" (so to
speak) is only available in animations

It is noticed that it
is possible to imitate this functionality (pause an transition)
using javascript, but if we depend only on CSS, this is impossible.

Reference: How do I pause CSS transition?

2. You are using a CSS property that is meant for animations, and there no transitions, which is: animation-play-state

Importante note


It is important to note that it is possible to remove a css transition, simply removing the transition property, or overwriting it, example: transition: none !important, but when removing a transition, it is not possible to resume it and the "animation" is lost in this process.

The solution


1. Create a function capable of restarting an animation, note that this is importante because at the end of the first animation (onAnimationEnd) it is necessary to restart the count of x seconds for the progress bar, otherwise, it would only work once.

Note: The key to restarting a CSS animation is to set the animation-name of an animation to 'none' and then setting it back to the original animation

Example:

const startAnimation = () => {
if (!progressRef.current) return;

const progress = progressRef.current;
progress.style.animationName = "none";
progress.style.width = "100%";

setTimeout(() => {
progress.style.animationName = "width";
progress.style.animationDuration = `${slideShowDelay}s`;
}, 50);
}

2. Call this function on every slide change, whether it's forward or previous, example:

First option:

const prevButtonHandler = () => {
startAnimation(); // <<- HERE
setCurrentSlide((prev) => {
const result = prev - 1;
if (result < 0) {
return images.length - 1;
}
return result;
});
};

const nextButtonHandler = useCallback(() => {
startAnimation(); // <<- HERE
setCurrentSlide((prev) => {
const result = prev + 1;
if (result >= images.length) {
return 0;
}
return result;
});
}, [images.length]);

OR

Second option:

Or better yet, we can put the startAnimation function inside useEffect which will capture every slide change, so no matter the slide is coming back or forward, the application will work normally.

Example:

useEffect(() => {
startAnimation();
}, [currentSlide, slideShowDelay]);

3. Create the animation frame in CSS:

@-webkit-keyframes width {
from {
width: 100%;
}
to {
width: 0%;
}
}

@keyframes width {
from {
width: 100%;
}
to {
width: 0%;
}
}

In the example above we have specified when the style will change by using the keywords "from" and "to" (which represents 0% (start) and 100% (complete)).

4. Change using onTransitionEnd to onAnimationEnd, example:

<div
onAnimationEnd={animationEndHandler}
ref={progressRef}
role={"progressbar"}
className={classes}
/>

The code

Typescript
import { Fragment, useEffect, useState, useCallback, useRef } from "react";
import "./Slider.css";

type Props = {
images: string[];
slideShowDelay?: number;
};
export default function Slider({
images,
slideShowDelay = 5
}: Props): JSX.Element {
const [currentSlide, setCurrentSlide] = useState<number>(0);
const progressRef = useRef<HTMLDivElement | null>(null);
const [animationState, setAnimationState] = useState("animate");

const startAnimation = () => {
if (!progressRef.current) return;
const progress = progressRef.current;
progress.style.animationName = "none";
progress.style.width = "100%";
setTimeout(() => {
progress.style.animationName = "width";
progress.style.animationDuration = `${slideShowDelay}s`;
}, 50);
}

const prevButtonHandler = () => {
setCurrentSlide((prev) => {
const result = prev - 1;
if (result < 0) {
return images.length - 1;
}
return result;
});
};
const nextButtonHandler = useCallback(() => {
setCurrentSlide((prev) => {
const result = prev + 1;
if (result >= images.length) {
return 0;
}
return result;
});
}, [images.length]);

useEffect(() => {
startAnimation();
}, [currentSlide, slideShowDelay]);

const slides = images.map((image, i) => {
const styles = {
transform: `translateX(${(i - currentSlide) * 100}%)`
};
return (
<Fragment key={i}>
<div className="slide" style={styles}>
<img src={image} alt="random" />
</div>
</Fragment>
);
});
const mouseHandler = () => {
setAnimationState("paused");
};
const mouseHandlerLeave = () => {
setAnimationState("animate");
};
const animationEndHandler = nextButtonHandler;
const classes = `progress-bar ${animationState}`;
const containerClasses = `slider-container ${animationState}`;
return (
<>
<div className="container">
<div
className={containerClasses}
onMouseEnter={mouseHandler}
onMouseLeave={mouseHandlerLeave}
>
{slides}
<button className="btn btn-prev" onClick={prevButtonHandler}>
{" "}
{"<"}{" "}
</button>
<button className="btn btn-next" onClick={nextButtonHandler}>
{" "}
{">"}{" "}
</button>
<div
onAnimationEnd={animationEndHandler}
ref={progressRef}
role={"progressbar"}
className={classes}
/>
</div>
</div>
</>
);
}
CSS
/* Safari 4.0 - 8.0 */
@-webkit-keyframes width {
from {
width: 100%;
}
to {
width: 0%;
}
}

@keyframes width {
from {
width: 100%;
}
to {
width: 0%;
}
}

.container {
width: 100vw;
display: grid;
place-items: center;
}
.container .slider-container {
width: 100%;
max-width: 600px;
height: 400px;
position: relative;
overflow: hidden;
}
.container .slider-container .slide {
position: absolute;
width: 100%;
max-width: 600px;
height: 400px;
transition: all 0.5s;
}
.container .slider-container .slide:hover {
animation-play-state: paused;
}
.container .slider-container .slide img {
object-fit: cover;
width: 600px;
height: 400px;
}
.container .slider-container .progress-bar {
position: absolute;
height: 10px;
bottom: 0;
left: 0;
width: 100%;
background-color: #61dafb;
}
.container .slider-container .progress-bar.animate {
animation-play-state: running;
}
.container .slider-container .progress-bar.paused {
animation-play-state: paused;
}
.container .slider-container .btn {
height: 40px;
width: 40px;
position: absolute;
border-radius: 50%;
top: calc(50% - 20px);
z-index: 1;
background-color: #ffffff;
font-size: 18px;
}
.container .slider-container .btn:hover {
cursor: pointer;
transform: scale(1.1);
}
.container .slider-container .btn.btn-prev {
left: 10px;
}
.container .slider-container .btn.btn-next {
right: 10px;
}

Try this:

Demo URL:

https://codesandbox.io/s/nifty-meninsky-pkijf0

Remarks


If this answer was not satisfactory, or confusing, or did not answer what was asked, please comment so I can edit it.

It's worth mentioning that I'm using google translator to answer, I apologize for any inconvenience


Related Topics



Leave a reply



Submit