64

I've tried to google and look from this forum a solution for my problem but no luck so far. I would like to pause my CSS3 animation (image slide show) by clicking a picture and also resume to the same animation by clicking a picture.

I know how to pause the slide show and I was also able to resume it once, but then it stops working if try to pause and resume more than one time. Here is how my code looks like:

<!DOCTYPE html>
<html>

<head>
<title></title>
<style type="text/css">
.pic {
    position: absolute;
    opacity: 0;
}

#pic1 {
    -webkit-animation: pic1 4s infinite linear;
}

#pic2 {
    -webkit-animation: pic2 4s infinite linear;
}

@-webkit-keyframes pic1 {
    0%   {opacity: 0;}
    5%   {opacity: 1;}
    45%  {opacity: 1;}
    50%  {opacity: 0;}
    100% {opacity: 0;}
}

@-webkit-keyframes pic2 {
    0%   {opacity: 0;}
    50%  {opacity: 0;}
    55%  {opacity: 1;}
    95%  {opacity: 1;}
    100% {opacity: 0;}
}
</style>

<script type="text/javascript">
function doStuff(){
    var pic1 = document.getElementById("pic1");
    var pic2 = document.getElementById("pic2");

    pic1.style.webkitAnimationPlayState="paused";
    pic2.style.webkitAnimationPlayState="paused";

    pic1.onclick = function(){
        pic1.style.webkitAnimationPlayState="running";
        pic2.style.webkitAnimationPlayState="running";
    }

    pic2.onclick = function(){
        pic1.style.webkitAnimationPlayState="running";
        pic2.style.webkitAnimationPlayState="running";
    }
}
</script>
</head>  

<body>
    <img id="pic1" class="pic" src="photo1.jpg" />
    <img id="pic2" class="pic" src="photo2.jpg" onclick="doStuff()" />
</body>                                                                

</html>

I don't want to use any JS libraries (e.g. jQuery) or any other external solution.

My guess is that my functions inside doStuff function are still running and that's why pause and resume works only once.

Is there a way to clear these functions after I have clicked them once? Or am I trying to do this in a totally wrong way? Help is appreciated. :)

5 Answers 5

174

I find it easier to do it with a css class. With it, you can use prefixes for every browser.

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

Then you only have to add or remove this class to your animated element yo pause / resume the animation.

Sign up to request clarification or add additional context in comments.

5 Comments

@nq1 CSS is the correct way to do it. Use JavaScript to add the class. This answer is also cross-browser compatible, unlike the accepted answer.
This seems like the better solution, but I can't get it to work. Does it require the animation to be infinite?
Old, I know but @Nate and anyone else. add !important to each line. CSS follows specificity and the more specific the rule, the more prominent its' properties. animation-play-state: paused !important; fixes this 'problem' (it's how css is designed, but it's a problem here). It may have worked for Luis because he did a simple test or there wasn't a specificity 'conflict'.
Would be better to just rearrange the CSS so that you don't have to use !important, since that ruins a lot of other things, an argument could be made for it's use in this case though, since it is pausing animations.
Simpler, cleaner and way to divide responsibility better. This should be on top. CSS classes should wrap all style changes as much as they can, by manipulation what classes are used when and where is how JS should interact with the style.
38

Here is a solution using javascript:

var imgs = document.querySelectorAll('.pic');

for (var i = 0; i < imgs.length; i++) {
  imgs[i].onclick = toggleAnimation;
  imgs[i].style.webkitAnimationPlayState = 'running';
}

function toggleAnimation() {
  var style;
  for (var i = 0; i < imgs.length; i++) {
    style = imgs[i].style;
    if (style.webkitAnimationPlayState === 'running') {
      style.webkitAnimationPlayState = 'paused';
      document.body.className = 'paused';
    } else {
      style.webkitAnimationPlayState = 'running';
      document.body.className = '';
    }
  }
}
.pic {
  position: absolute;
  opacity: 0;
}

#pic1 {
  -webkit-animation: pic1 4s infinite linear;
}

#pic2 {
  -webkit-animation: pic2 4s infinite linear;
}

@-webkit-keyframes pic1 {
  0% {
    opacity: 0;
  }
  5% {
    opacity: 1;
  }
  45% {
    opacity: 1;
  }
  50% {
    opacity: 0;
  }
  100% {
    opacity: 0;
  }
}

@-webkit-keyframes pic2 {
  0% {
    opacity: 0;
  }
  50% {
    opacity: 0;
  }
  55% {
    opacity: 1;
  }
  95% {
    opacity: 1;
  }
  100% {
    opacity: 0;
  }
}

.paused {
  background-color: #ddd;
}
<img id="pic1" class="pic" src="http://placehold.it/200x200/ff0000/ffffff">
<img id="pic2" class="pic" src="http://placehold.it/200x200/ff00ff/ffffff">

jQuery solution (shorter and more readable):

var imgs = $('.pic'),
  playState = '-webkit-animation-play-state';

imgs.click(function() {
  imgs.css(playState, function(i, v) {
    return v === 'paused' ? 'running' : 'paused';
  });
  $('body').toggleClass('paused', $(this).css(playState) === 'paused');
});
.pic {
  position: absolute;
  opacity: 0;
}

#pic1 {
  -webkit-animation: pic1 4s infinite linear;
}

#pic2 {
  -webkit-animation: pic2 4s infinite linear;
}

@-webkit-keyframes pic1 {
  0% {
    opacity: 0;
  }
  5% {
    opacity: 1;
  }
  45% {
    opacity: 1;
  }
  50% {
    opacity: 0;
  }
  100% {
    opacity: 0;
  }
}

@-webkit-keyframes pic2 {
  0% {
    opacity: 0;
  }
  50% {
    opacity: 0;
  }
  55% {
    opacity: 1;
  }
  95% {
    opacity: 1;
  }
  100% {
    opacity: 0;
  }
}

.paused {
  background-color: #ddd;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<img id="pic1" class="pic" src="http://placehold.it/200x200/ff0000/ffffff">
<img id="pic2" class="pic" src="http://placehold.it/200x200/ff00ff/ffffff">

1 Comment

Please is it possible to detect the how much times left when pausing ? Thx
10

This is to extend the answer given by Luis Hijarrubia

.pause {
   -webkit-animation-play-state: paused !important; 
   -moz-animation-play-state: paused !important; 
   -o-animation-play-state: paused !important;
    animation-play-state: paused !important;
}

In my page I was triggering the change of class from the parent element. All I wanted to do was rotate the image inside. But it seems that because I was not using the hover, the adding of the paused class made no difference to the animation state.

The use of !important ensured that these values were overwritten by the new added CSS values.

3 Comments

Just to clarify, this is because of css specificity. A script that adds the property directly to the element (like Sime's answer) would not have this issue because "inline" styles override rules from stylesheets by default. developer.mozilla.org/en-US/docs/Web/CSS/Specificity
This is a specific issue cuased by your HTML & CSS. At best this should be a comment, it doesn't answer the actual question.
Came here to post this answer if it wasn't posted. In my case, I needed to pause a few simultaneous animations and found this to be the simplest way. It also allows you to add effects like .pause:hover if it suits the need.
1
var e = document.getElementsById("Your_Id");


e.addEventListener("animationstart", listener, false);
e.addEventListener("animationend", listener, false);
e.addEventListener("animationiteration", listener, false);


function listener(e) {  alert("Your POSITION parameter:" + .target.style.position);
  switch(e.type) {
    case "animationstart":
      d = "Started: elapsed time is " + e.elapsedTime;
      break;
    case "animationend":
      d = "Ended: elapsed time is " + e.elapsedTime;
      break;
    case "animationiteration":
      d= "New loop started at time " + e.elapsedTime;  alert("pausing for 1 seconddddddd!!!!!!!"); e.target.style.animationPlayState = "paused";        window.setTimeout(function(){e.target.style.animationPlayState = "running";}, 1000);
      break;
  }
}

Comments

-1

I havent tested it but perhaps something like this?

<!DOCTYPE html>
<html>
<head>
<title></title>
<style type="text/css">
.pic {   position: absolute;opacity: 0;  }
.pic1 {  -webkit-animation: pic1 4s infinite linear;   }
.pic2 {  -webkit-animation: pic2 4s infinite linear;   }
@-webkit-keyframes pic1 {  0%   {opacity: 0;}
                           5%   {opacity: 1;}
                           45%  {opacity: 1;}
                           50%  {opacity: 0;}
                           100% {opacity: 0;}    }
@-webkit-keyframes pic2 {  0%   {opacity: 0;}
                           50%  {opacity: 0;}
                           55%  {opacity: 1;}
                           95%  {opacity: 1;}
                           100% {opacity: 0;}    }
</style>
<script type="text/javascript">
function doStuff(){
    var pic1 = document.getElementById("pic1");
    var pic2 = document.getElementById("pic2");

    pic1.className="pic paused";
    pic2.className="pic paused";

    pic1.onclick = function(){
       pic1.className="pic pic1";
       pic2.className="pic pic2";
    }
    pic2.onclick = function(){
       pic1.className="pic pic1";
       pic2.className="pic pic2";
    }
}
</script>
</head>  
<body>
    <img id="pic1" class="pic pic1" src="photo1.jpg" />
    <img id="pic2" class="pic pic2" src="photo2.jpg" onclick="doStuff()" />
</body>                                                                 
</html>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.