Animated canvas arc with easing
I'm drawing a non-traditional ring-clock in canvas. The time is represented by a second ring, second hand, minute ring, and hour ring. I am using webkit/mozRequestAnimationFrame to draw at the appropriate time. I would like to modify the second ring to animate to th开发者_Python百科e next second quickly (125ms - 250ms) and with Quadratic easing (instead of that dreaded snap).
Much like the Raphael JS Clock animates its second ring, except it uses different easing: http://raphaeljs.com/polar-clock.html
JS Fiddle Links (must view in Chrome, Firefox, or Webkit Nightly):
Fiddle: http://jsfiddle.net/thecrypticace/qmwJx/
Full screen Fiddle: http://jsfiddle.net/thecrypticace/qmwJx/embedded/result/
Any help would be very much appreciated!
This comes close but is still really jerky:
var startValue;
if (milliseconds < 500) {
if (!startValue) startValue = milliseconds;
if (milliseconds - startValue <= 125) {
animatedSeconds = seconds - 0.5 + Math.easeIn(milliseconds - startValue, startValue, 1000 - startValue, 125)/1000;
} else {
animatedSeconds = seconds;
}
drawRing(384, 384, 384, 20, animatedSeconds / 60, 3 / 2 * Math.PI, false);
} else {
drawRing(384, 384, 384, 20, seconds / 60, 3 / 2 * Math.PI, false);
startValue = 0;
}
It is a mater of math:
drawRing(384, 384, 384, 20, seconds / 60, 3 / 2 * Math.PI, false);
This is the line which is drawing the seconds circle. So the problem is that in any given moment you have something like 34/60, 35/60 and so on. This means your seconds circle is 60/60 thus not using the milliseconds, and drawing it each second.
The linear easing solution: make your seconds circle 60 000 / 60 000 -> 60 seconds by 1000 millisecond each. And the math:
drawRing(384, 384, 384, 20, ((seconds*1000)+milliseconds) / 60000, 3 / 2 * Math.PI, false);
The In Out Quadric solution or choose one these :
Math.easeInOutQuad = function (t, b, c, d) {
t /= d/2;
if (t < 1) return c/2*t*t + b;
t--;
return -c/2 * (t*(t-2) - 1) + b;
};
And I optimized and changed your code:
//+1 animation happens before the second hand
//-1 animation happens after the second hand
animatedSeconds = seconds+1;
if (milliseconds > 10) {
if (!startValue) { startValue = milliseconds; }
if (milliseconds - startValue <= 100) {
animatedSeconds -= -0.5+ Math.easeInOutQuad(milliseconds - startValue, startValue, 1000 - startValue, 125) / 1000;
}
} else {
startValue = 0;
}
drawRing(384, 384, 384, 20, animatedSeconds / 60, 3 / 2 * Math.PI, false);
Hopefully this is what you are looking for.
精彩评论