3

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 the 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):

  1. Fiddle: http://jsfiddle.net/thecrypticace/qmwJx/

  2. 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;
}
TheCrypticAce
  • 173
  • 1
  • 7
  • 2
    ... help with what? ;-). You should spell out your question here, not just link to a Fiddle... – Jonas Heidelberg Sep 18 '11 at 23:18
  • 1
    I said it right here: "modify the second ring to animate...instead of snap..." Basically I just want to add animation to the second ring so, instead of just displaying the next value, it animates nicely. – TheCrypticAce Sep 18 '11 at 23:36

1 Answers1

2

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.

Bakudan
  • 19,134
  • 9
  • 53
  • 73
  • This is close to what I want. However, I am already doing this for the second hand. Also, it is not redrawing every millisecond, Google requestAnimationFrame to find out why (browser controls animation loop). My problem is I need to animate the second ring akin to the Raphael JS Polar Clock example. From second to second it has a quick animation, that takes less than one second to complete, to draw the next second on the ring. – TheCrypticAce Sep 19 '11 at 00:49
  • Added in something I experimented with, it is close, but not quite, because the animation is really jerky. Also updated JS Fiddle example with new code. – TheCrypticAce Sep 19 '11 at 01:16
  • This is extremely close but there are a few times when it jumps from a full circle the the right value (semi-repeatedly). However, this is extremely close and I will see if I can't work out the math tomorrow based on this. Thank you! – TheCrypticAce Sep 19 '11 at 02:35