Search code examples
iosimageanimationsdkcaanimation

How to move graphic in an arc path on iOS... as in a meter or clock face


This is the result of what I want to achieve:


(source: mouseaddict.com)

I have static images for my app, but i want to add motion to them.

Imagine a meter. It has a needle that is locked at the bottom (at 6:00 on a round-clock-style-face) and whose needle-top swivels from left to right in an arc. the arc (zero) starts with the needle pointed toward (roughly) the 9:30 position on a round-clock-style-face and the top-most part of that arc should end at roughly 2:30 on a round-clock-style-face.

I have several graphical elements 1) the round meter face (png) and 2) the verticaly oriented png file of a meter needle. I need to cause the needle to move within the round face in an arc'ing pattern.

So, assuming the two requirements above, what is the best way to swivel the needle within the meter using animation?

I have seen this: Speedometer -- but is this the best way? My main issue is that I want the needle locked at the bottom and move left-to-right only a small amount..as WELL as the fact that there is little (actually no) documentation on it. Things like "calculateDeviationAngle" are unexplained.

Also the Speedometer seems to move a large amount and the pivot point on that example would not work...(i dont think)

I would like to call this with a command like:

[self moveNeedleToPosition:degreeOrClockFaceNumber] and have it move from it's current position to a bit past the degreeOrClockFaceNumber and bounce back to rest at degreeOrClockFaceNumber.

TIA


Solution

  • I did the following: I broke the image up into several pieces. The outline (black) portion, the backgrounds and the needle. Each piece having the same exact "footprint" (shapes).

    Assuming theImageView is the imageView for the needle (layered on top of the other two imageViews), I created the following function:

    -(void) rotateNeedle:(UIImageView *)theImageView toAngle:(float) theAngle
    {
        [UIView animateWithDuration:0.5
                              delay: 0.0
                            options: UIViewAnimationOptionCurveEaseInOut
                         animations:^{
                             theImageView.transform =CGAffineTransformMakeRotation((M_PI / 180) * (theAngle + 10));
                         }
                         completion:^(BOOL finished){
                             //
                             [UIView animateWithDuration:0.5
                                              animations:^{
                                                  theImageView.transform = CGAffineTransformMakeRotation((M_PI / 180) * theAngle);
                                              }];
    
    
                         }];
    
    }
    

    The first animation in the block performs the "shoot-past" portion of the animation...ie: moving 10 degrees past the actual value. The second animation in the completion block then "bounces" the needle back to the correct value. The speed of these animations create the physics effect. It works quite well for me.