g_low
g_low

Reputation: 2455

CoreAnimation rotation transformation animation direction

Is there a simple way to specify whether an image should rotate clockwise or anti-clockwise in objective C? I have a speedometer with a needle (a design that reflects prices of automobiles) - it is working fine, except when it is closer for the needle to rotate down and out of the screen over to the other side. I want it always to rotate counterclockwise to go to lower numbers and clockwise to go to higher numbers. Here is my code segment:

// figure out the minimum and maximum prices shown on the 
// speedometer
float min = [_a.text floatValue] * 1000;
float max = [_g.text floatValue] * 1000;

// set calibration between number labels to be small or large
int cal = SMALL_CALIBRATION;
if ([_stickerPriceSetting floatValue] >= TRIGGERPRICE)
    cal = LARGE_CALIBRATION;

// set an animation duration of 1.5 seconds for the needle rotation
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:1.5];

// low prices (off speedometer)
if (price < (min - cal)) 
    _needle.transform = CGAffineTransformMakeRotation(- M_PI/12); 

// price too high (off speedometer)
else if (price  > (max + cal)) 
    _needle.transform = CGAffineTransformMakeRotation(M_PI * 13/12); 

// need to have needle point to the price
else {
    float delta = (max - min);
    float price_point = price - min;
    _needle.transform = CGAffineTransformMakeRotation(price_point/delta * M_PI);
}

 [UIView commitAnimations];

Upvotes: 2

Views: 1579

Answers (2)

rob mayoff
rob mayoff

Reputation: 385590

You can do it by animating the layer property transform.rotation:

// figure out the minimum and maximum prices shown on the 
// speedometer
float min = [_a.text floatValue] * 1000;
float max = [_g.text floatValue] * 1000;

// set calibration between number labels to be small or large
int cal = SMALL_CALIBRATION;
if ([_stickerPriceSetting floatValue] >= TRIGGERPRICE)
    cal = LARGE_CALIBRATION;

CGFloat angle;
if (price < min - cal)
    angle = -M_PI / 12;
else if (price > max + cal)
    angle = M_PI * 13 / 12;
else
    angle = M_PI * (price - min) / (max - min);

[UIView animateWithDuration:1.5 animations:^{
    [(id)_needle.layer setValue:[NSNumber numberWithFloat:angle]
        forKeyPath:@"transform.rotation"];
}];

If you import QuartzCore/QuartzCore.h you won't need the (id) cast.

Upvotes: 2

Felix
Felix

Reputation: 35384

I had the same problem with a speedometer. You cannot specify the rotation direction when animating the transform-property. It will always take the shortest way. I solved the problem by doing 2 animations in case the angle is greater than 180 degrees (2nd animation starts after 1st finishes). You have to pay attention for the correct animation times so that it animates smooth.

Upvotes: 0

Related Questions