// 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>