Preface: This is not a "complete" answer, as such, but rather the best I could come up within a reasonable amount of time. It seemed a shame to not post my results even though they're not a perfect answer...
It also only covers jQuery.animate
; I did not investigate CSS animations.
For jQuery, at least, this is difficult; it's not like the browser "knows" about
a jQuery animation. Effectively, all jQuery does is schedule a function to run n times with setTimeout()
or setInterval()
, where each function call moves the element by a few pixels (or changed something else a little bit), giving the illusion of smooth animations.
Your browser would, somehow, have to keep track of which function call belongs
to which animation. Since these are anonymous functions, this is not really
easy... Some sort of special debugging statement could be used, but AFAIK no
browser implements a feature like this.
What we can do is measure the number of updates jQuery.animate
does with the
step
callback:
A function to be called for each animated property of each animated element.
This function provides an opportunity to modify the Tween object to change the
value of the property before it is set.
This will only give you an approximation, at best. But perhaps it's good
enough; I've created an example (see below), which gives me these results on my
system:
"a: 52 updates; 26 upd/s"
"b: 27 updates; 54 upd/s"
"c: 1080 updates; 360 upd/s"
Your system might vary, but suggests that:
a
was the cheapest;
b
was slightly more exensive, but also actually quite cheap
c
is several times more expensive than a
or b
.
To check if this is roughly accurate, I enabled only one animation at a
time, and checked if this corresponds to what Chromium & Firefox developer tools report:
- Chromium:
a
spent 40ms non-idle; Firefox: 2 calls to n.fx.tick
- Chromium:
b
spent 40ms non-idle; Firefox: 4 calls to n.fx.tick
- Chromium:
c
spent 130ms non-idle; Firefox: 36 calls to n.fx.tick
Which is indeed roughly accurate, though not entirely.
Will this be useful enough for your application? I have no idea. Maybe, maybe not...
Test HTML:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Animations test</title>
<style>
div { width: 200px; height: 100px; position: relative; color: #fff; }
#test_a { background-color: green; }
#test_b { background-color: red; }
#test_c { background-color: blue; }
</style>
</head>
<body>
<div id="test_a"></div>
<div id="test_b"></div>
<div id="test_c"></div>
<script src="http://code.jquery.com/jquery-2.1.1.min.js"></script>
<script src="anim.js"></script>
</body>
</html>
Test JS in CoffeeScript:
go = ->
a = b = c = 0
log = (n, t) ->
eval "u = #{n}"
str = "#{n}: #{u} updates; #{parseInt u / t, 10} upd/s"
$("#test_#{n}").html str
console.log str
$('#test_a').animate {left: '500px'},
duration: 500
step: -> a += 1
complete: -> log 'a', .5
$('#test_b').animate {top: '100px', left: '100px', opacity: 0.3, width: '500px'},
duration: 200
step: -> b += 1
complete: -> log 'b', 2
$('#test_c').animate {left: '500px', top: '300px', opacity: .75, height: '50px', width: '400px'},
duration: 3000
step: -> c += 1
complete: -> log 'c', 3
$(document).ready -> setTimeout go, 500
And the same JS compiled for convenience:
// Generated by CoffeeScript 1.7.1
(function() {
var go;
go = function() {
var a, b, c, log;
a = b = c = 0;
log = function(n, t) {
var str;
eval("u = " + n);
str = "" + n + ": " + u + " updates; " + (parseInt(u / t, 10)) + " upd/s";
$("#test_" + n).html(str);
return console.log(str);
};
$('#test_a').animate({
left: '500px'
}, {
duration: 500,
step: function() {
return a += 1;
},
complete: function() {
return log('a', .5);
}
});
return;
$('#test_b').animate({
top: '100px',
left: '100px',
opacity: 0.3,
width: '500px'
}, {
duration: 200,
step: function() {
return b += 1;
},
complete: function() {
return log('b', 2);
}
});
return $('#test_c').animate({
left: '500px',
top: '300px',
opacity: .75,
height: '50px',
width: '400px'
}, {
duration: 3000,
step: function() {
return c += 1;
},
complete: function() {
return log('c', 3);
}
});
};
$(document).ready(function() {
return setTimeout(go, 500);
});
}).call(this);