121

I am trying to replicate an Apple style activity indicator (sundial loading icon) by using a PNG and CSS3 animation. I have the image rotating and doing it continuously, but there seems to be a delay after the animation has finished before it does the next rotation.

@-webkit-keyframes rotate {
  from {
    -webkit-transform: rotate(0deg);
  }
  to { 
    -webkit-transform: rotate(360deg);
  }
}
#loading img
{
    -webkit-animation-name:             rotate; 
    -webkit-animation-duration:         0.5s; 
    -webkit-animation-iteration-count:  infinite;
    -webkit-transition-timing-function: linear;
    }

I have tried changing the animation duration but it makes no difference, if you slow it right down say 5s its just more apparent that after the first rotation there is a pause before it rotates again. It's this pause I want to get rid of.

Any help is much appreciated, thanks.

Daniel Daranas
  • 22,454
  • 9
  • 63
  • 116
Gcoop
  • 3,372
  • 4
  • 26
  • 35
  • 14
    Webkit-specific code doesn't make it less CSS3.. considering that none of the other providers did provide equal functions at that time :) – 19h May 27 '12 at 15:47
  • 4
    Shouldn't the animation run from 0 to 359? If it ran from 0 to 360, then you'd have the frame at 0 played twice, since frame 0 and frame 360 would be the same... – Brad Parks Oct 17 '12 at 15:17
  • 1
    @BradParks On the other hand, if you go from 0 to 359, then the animation that should take place at 359.5 is skipped completely. In most cases, the overlap of 0 and 360 will be so quick as to be unnoticable. – Blazemonger Jul 09 '13 at 14:10
  • @Blazemonger not necessarily. You can try it out yourself in a jsfiddle and see that depending on the animation duration it may not be so subtle. – Ilan Biala Jan 10 '14 at 20:59
  • 1
    this whole '359 degrees' thing is silly - you have no control over the step of the animation. assuming a 1 second animation with 60fps that's 6 degrees per frame so you should stop at '354 degrees'. but like I said you don't have control over the frame rate here so it's pretty futile. I'd imagine a smart implementation could detect 0-360 and adjust accordingly. I just multiplied the time and angle by 100 - ie. 0 deg to 36000 degrees so the theoretical glitch will only occur every 100 rotations. but I've found you're going to get animation glitches no matter what you do anyway – Simon_Weaver Oct 02 '14 at 00:39

6 Answers6

71

Your issue here is that you've supplied a -webkit-TRANSITION-timing-function when you want a -webkit-ANIMATION-timing-function. Your values of 0 to 360 will work properly.

thomaux
  • 19,133
  • 10
  • 76
  • 103
rrahlf
  • 726
  • 6
  • 4
  • A typical copy-paste error. Thanks a lot! (I actually got my css from [shareaholic](http://www.shareaholic.com/) and because of the wrongly named property, it used the default `ease` timing function). – doekman Feb 15 '12 at 21:24
55

You also might notice a little lag because 0deg and 360deg are the same spot, so it is going from spot 1 in a circle back to spot 1. It is really insignificant, but to fix it, all you have to do is change 360deg to 359deg

my jsfiddle illustrates your animation:

#myImg {
    -webkit-animation: rotation 2s infinite linear;
}

@-webkit-keyframes rotation {
    from {-webkit-transform: rotate(0deg);}
    to   {-webkit-transform: rotate(359deg);}
}

Also what might be more resemblant of the apple loading icon would be an animation that transitions the opacity/color of the stripes of gray instead of rotating the icon.

Andrew
  • 18,680
  • 13
  • 103
  • 118
Ilan Biala
  • 3,319
  • 5
  • 36
  • 45
  • 3
    Your JS Fiddle contains the most succinct implementation I've seen for simple image rotation - perfect (and thanks for posting). – Philip Murphy Feb 05 '13 at 23:04
  • thanks let me know if you need any other help, by the way, I used the webkit prefixes for the animation but you should also include the mozilla prefixes because they use -moz-css rule instead. – Ilan Biala Feb 06 '13 at 15:12
  • you can also multiply the time and angle by 100 - ie. 0 deg to 36000 degrees :-) – Simon_Weaver Oct 02 '14 at 00:38
  • @Simon_Weaver still would need to be 35999deg to not see any double frames. – Ilan Biala Oct 03 '14 at 02:27
  • 2
    @IlanBiala except I very much doubt your graphics card is running at 720fps ;-) It's impossible for you know what the increment is between frames without knowing the framerate. If anything you may as well put 348 degrees because at half a second at 60fps each frame would advance by 12 degrees. I'd rather just put 360 and hope someone smart programmed the browser to automatically adjust – Simon_Weaver Oct 03 '14 at 02:32
  • don't forget to remove vendor prefixes these days – danday74 May 27 '21 at 15:19
28

You could use animation like this:

-webkit-animation: spin 1s infinite linear;

@-webkit-keyframes spin {
    0%   {-webkit-transform: rotate(0deg)}
    100% {-webkit-transform: rotate(360deg)}
}
Kinglybird
  • 319
  • 3
  • 8
8

If you're only looking for a webkit version this is nifty: http://s3.amazonaws.com/37assets/svn/463-single_spinner.html from http://37signals.com/svn/posts/2577-loading-spinner-animation-using-css-and-webkit

Tudor
  • 4,137
  • 5
  • 38
  • 54
  • 9
    Very cool. I actually collect spinners, both `GIF` and `CSS`. [My collection](http://zanstra.home.xs4all.nl/picks/progress.html#css_animations). If you know more, please let me know. – doekman Feb 15 '12 at 21:34
1

I made a small library that lets you easily use a throbber without images.

It uses CSS3 but falls back onto JavaScript if the browser doesn't support it.

// First argument is a reference to a container element in which you
// wish to add a throbber to.
// Second argument is the duration in which you want the throbber to
// complete one full circle.
var throbber = throbbage(document.getElementById("container"), 1000);

// Start the throbber.
throbber.play();

// Pause the throbber.
throbber.pause();

Example.

alex
  • 479,566
  • 201
  • 878
  • 984
1

Your code seems correct. I would presume it is something to do with the fact you are using a .png and the way the browser redraws the object upon rotation is inefficient, causing the hang (what browser are you testing under?)

If possible replace the .png with something native.

see; http://kilianvalkhof.com/2010/css-xhtml/css3-loading-spinners-without-images/

Chrome gives me no pauses using this method.

Alex
  • 4,916
  • 1
  • 20
  • 15
  • Perfect, I am pretty sure your assumption is correct however I am using a PNG because my loading icon isn't a sundial its a nuclear style symbol... It doesn't have to be though so I can change it to the method you suggest - thanks! – Gcoop Apr 06 '10 at 10:56