// prepare the animation canvas and the draw canvas var animcanvas = document.createElement( 'canvas' ), animctx = animcanvas.getContext( '2d' ), drawcanvas = document.createElement( 'canvas' ), drawctx = drawcanvas.getContext( '2d' ); // dimensions and container element var container = document.querySelector('section'), height = width = 300, halfwidth = width / 2, halfheight = height / 2, offset = i = x = 0, radius = height / 2 - 10; function init(){ // check if the browser supports CSS animation var domPrefixes = 'Webkit Moz O ms Khtml'.split(' '); var pfx = false; for(var i = 0; i < domPrefixes.length ;i++ ) { if( animcanvas.style[ domPrefixes[i] + 'AnimationName' ] !== undefined ) { pfx = domPrefixes[i]; break; } } animcanvas.width = drawcanvas.width = width; animcanvas.height = drawcanvas.height = height; drawctx.save(); drawctx.translate( halfwidth, halfheight ); while( radius > 10 ) { drawctx.fillStyle = i % 2 === 0 ? '#000' : '#fff'; radius -= 6; x = Math.sin( i / 2 ) * 10; drawctx.beginPath(); drawctx.arc( x, 0, radius, 0, Math.PI * 2 ,true ); drawctx.closePath(); drawctx.fill(); i++; } drawctx.restore(); // if the browser supports CSS3 animation, create a new animation if( pfx !== false ) { drawcanvas.style[ pfx + 'AnimationDuration' ] = '1s'; drawcanvas.style[ pfx + 'AnimationTimingFunction'] = 'linear'; drawcanvas.style[ pfx + 'AnimationIterationCount'] = 'infinite'; drawcanvas.style[ pfx + 'AnimationName'] = 'rotate'; var csspfx = pfx.toLowerCase(), keyframes = '@-' + csspfx + '-keyframes rotate { '+ 'from { -' + csspfx + '-transform:rotate( 0deg ); }'+ 'to { -' + csspfx + '-transform:rotate( 360deg ); }'+ '}'; if( document.styleSheets && document.styleSheets.length ) { document.styleSheets[0].insertRule( keyframes, 0 ); } else { var s = document.createElement( 'style' ); s.innerHTML = keyframes; document.getElementsByTagName( 'head' )[ 0 ].appendChild( s ); } // ^ this makes me feel dirty, is there a cleaner way without // generating a style element? container.appendChild( drawcanvas ); var msg = document.createElement('span'); msg.innerHTML += '<span>Using CSS animation</span>'; container.appendChild(msg); // if the browser has no CSS animation, do a canvas animation } else { container.appendChild( animcanvas ); var msg = document.createElement( 'span' ); msg.innerHTML += '<span>Using an animation loop'; if(requestAnimationFrame.toString().indexOf( 'mation' ) !== -1 ) { msg.innerHTML += ' with requestAnimationFrame'; } else { msg.innerHTML += ' without requestAnimationFrame'; } msg.innerHTML += '</span>'; container.appendChild( msg ); loop(); } } // canvas animation loop function loop(){ animctx.clearRect( 0, 0, width, height ); animctx.save(); animctx.translate( halfwidth, halfheight ); offset += 0.06; animctx.rotate( offset ); animctx.fill(); animctx.drawImage( drawcanvas, -halfwidth, -halfheight ); animctx.restore(); requestAnimationFrame( loop, 60 ); } /** * Provides requestAnimationFrame in a cross browser way. * http://paulirish.com/2011/requestanimationframe-for-smart-animating/ */ if ( !window.requestAnimationFrame ) { window.requestAnimationFrame = ( function() { return window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function( callback, fps ) { window.setTimeout( callback, 1000 / fps ); }; } )(); } init();
<section></section>