Il DOM dispone di tre eventi specifici che possiamo usare per monitorare le animazioni CSS. Un inizio (animationstart), una fine (animationend) ed una ripetizione (animationiteration). Il problema è che attualmente i browser implementano questi eventi attraverso i loro prefissi proprietari.

Per prima cosa definiamo una semplice animazione:


@-webkit-keyframes move {
	0% {
		left: 100px;
	}
	
	50% {
		width: 150px;
		height: 150px;
	}
	
	100% {
		width: 100px;
		height: 100px;
		left: 0;
	}
}

@-moz-keyframes move {
	0% {
		left: 100px;
	}
	
	50% {
		width: 150px;
		height: 150px;
	}
	
	100% {
		width: 100px;
		height: 100px;
		left: 0;
	}
}

@-ms-keyframes move {
	0% {
		left: 100px;
	}
	
	50% {
		width: 150px;
		height: 150px;
	}
	
	100% {
		width: 100px;
		height: 100px;
		left: 0;
	}
}

@keyframes move {
	0% {
		left: 100px;
	}
	
	50% {
		width: 150px;
		height: 150px;
	}
	
	100% {
		width: 100px;
		height: 100px;
		left: 0;
	}
}

.animate {
	-webkit-animation: move 2s ease-in 2s 3 alternate;
	-moz-animation: move 2s ease-in 2s 3 alternate;
	-ms-animation: move 2s ease-in 2s 3 alternate;
		animation: move 2s ease-in 2s 3 alternate;
}

Quindi definiamo una funzione di utility per uniformare i nomi degli eventi nei vari browser:


var prefixes = [ 'webkit', 'moz', 'MS', 'o', '' ];
var prefixedEvent = function( element, type, callback ) {
	for ( var p = 0; p < prefixes.length; p++ ) {
		if ( !prefixes[p] ) { 
			type = type.toLowerCase();
		}
		element.addEventListener( prefixes[p] + type, callback, false );
	}
}

A questo punto possiamo creare un unico handler che andrà ad eseguire un'azione diversa in base al tipo di evento:


var animationHandler = function( e ) {
	var item = document.createElement( 'li' ),
		evtType = e.type,
		evtStr = evtType.toLowerCase();
	
	if( evtStr.indexOf( 'start' ) != - 1 ) {
		item.innerHTML = 'Event started at time ' + e.elapsedTime;
	}
	
	if( evtStr.indexOf( 'end' ) != - 1 ) {
		item.innerHTML = 'Event ended at time ' + e.elapsedTime;
	}
	
	if( evtStr.indexOf( 'iteration' ) != - 1 ) {
		item.innerHTML = 'Now entering the loop at time ' + e.elapsedTime;
	}
  	
  	document.getElementById( 'log' ).appendChild( item );
};

Il codice finale sarà il seguente:


document.addEventListener( 'DOMContentLoaded', function() {

	var test = document.getElementById( 'test' );
	var run = document.getElementById( 'run' );
	
	prefixedEvent( test, 'AnimationStart', animationHandler );
	prefixedEvent( test, 'AnimationEnd', animationHandler );
	prefixedEvent( test, 'AnimationIteration', animationHandler );
	
	run.addEventListener( 'click', function() {
		test.className = 'animate';
	
	}, false );
	
	
	
}, false );