Search code examples
iosanimationrotatetransform

How to make smooth rotation


I want to make smooth rotation of a compass, like i have in my Android app :

https://www.dropbox.com/s/md93ys92938njaf/2014-07-31%2012.24.19.mov

To be the same in my iOS app

However this is my current state: https://www.dropbox.com/s/kk6l3atkg7oc0k2/VID_20140731_122703.mp4

-(void)rotate:(UIView *)v angle:(float)angle{

    CGFloat duration = 0.5;//animated ? 0.5 : 0.01;

    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
    animation.fromValue = [[v.layer presentationLayer] valueForKeyPath:@"transform.rotation.z"];
    animation.toValue = @(angle);
    animation.duration = duration;
    animation.fillMode = kCAFillModeForwards;
    animation.repeatCount = 0;
    animation.removedOnCompletion = NO;
    animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
    [v.layer setAnchorPoint:CGPointMake(0.5, 0.60)];
    [v.layer addAnimation:animation forKey:@"transform.rotation.z"];
}


-(void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading{



    float oldRad =  -manager.heading.magneticHeading * M_PI / 180.0f;

    float newRad =  -newHeading.magneticHeading * M_PI / 180.0f;


    [self rotate:_myLocationButton.imageView angle:newHeading.magneticHeading];
    LogInfo(@"%f (%f) => %f (%f)", manager.heading.trueHeading, oldRad, newHeading.trueHeading, newRad);

}

How to make the rotation smoother, and around the center point of the star ?

EDIT: the actual problem:1. it rotates TOO QUICKLY 2. it stops in the wrong position

see video https://www.dropbox.com/s/lv4uyhe7oidq5m3/VID_20140731_133116.mp4

edit:

log output values:

2014-07-31 14:24:10.702 App[1040:60b] I,-[WBGoogleMapViewController rotate:fromAgnle:angle:]:160

previousValue:-0.504699 newValue:-0.999089

2014-07-31 14:24:10.704 App[1040:60b] I,-[WBGoogleMapViewController locationManager:didUpdateHeading:]:151

manager.heading.trueheading: 61.573509 (oldRad: -0.999089) => newHeading.trueHeading:61.573509 (newRad:-0.999089)

2014-07-31 14:24:10.705 App[1040:60b] D,-[Prefs getLocation]:81

coordinate:31.2719341228076,34.83940961773958

2014-07-31 14:24:14.525 App[1040:60b] I,-[WBGoogleMapViewController rotate:fromAgnle:angle:]:160

previousValue:-0.999089 newValue:-0.909013

2014-07-31 14:24:14.527 App[1040:60b] I,-[WBGoogleMapViewController locationManager:didUpdateHeading:]:151

manager.heading.trueheading: 56.412567 (oldRad: -0.909013) => newHeading.trueHeading:56.412567 (newRad:-0.909013)

2014-07-31 14:24:14.528 App[1040:60b] D,-[Prefs getLocation]:81

coordinate:31.2719341228076,34.83940961773958

2014-07-31 14:24:14.759 App[1040:60b] I,-[WBGoogleMapViewController rotate:fromAgnle:angle:]:160

previousValue:-0.828879 newValue:-0.724668

2014-07-31 14:24:14.761 App[1040:60b] I,-[WBGoogleMapViewController locationManager:didUpdateHeading:]:151

manager.heading.trueheading: 45.850368 (oldRad: -0.724668) => newHeading.trueHeading:45.850368 (newRad:-0.724668)

2014-07-31 14:24:14.763 App[1040:60b] D,-[Prefs getLocation]:81

coordinate:31.2719341228076,34.83940961773958

2014-07-31 14:24:18.406 App[1040:60b] I,-[WBGoogleMapViewController rotate:fromAgnle:angle:]:160

previousValue:-0.724668 newValue:-0.814539

2014-07-31 14:24:18.408 App[1040:60b] I,-[WBGoogleMapViewController locationManager:didUpdateHeading:]:151

manager.heading.trueheading: 50.999573 (oldRad: -0.814539) => newHeading.trueHeading:50.999573 (newRad:-0.814539)

2014-07-31 14:24:18.409 App[1040:60b] D,-[Prefs getLocation]:81

coordinate:31.2719341228076,34.83940961773958

2014-07-31 14:24:18.553 App[1040:60b] I,-[WBGoogleMapViewController rotate:fromAgnle:angle:]:160

previousValue:-0.460764 newValue:-0.912728

2014-07-31 14:24:18.555 App[1040:60b] I,-[WBGoogleMapViewController locationManager:didUpdateHeading:]:151

manager.heading.trueheading: 56.625385 (oldRad: -0.912728) => newHeading.trueHeading:56.625385 (newRad:-0.912728)

2014-07-31 14:24:18.556 App[1040:60b] D,-[Prefs getLocation]:81

coordinate:31.2719341228076,34.83940961773958

2014-07-31 14:24:18.963 App[1040:60b] I,-[WBGoogleMapViewController rotate:fromAgnle:angle:]:160

previousValue:-0.912728 newValue:-1.015497

2014-07-31 14:24:18.965 App[1040:60b] I,-[WBGoogleMapViewController locationManager:didUpdateHeading:]:151

manager.heading.trueheading: 62.513649 (oldRad: -1.015497) => newHeading.trueHeading:62.513649 (newRad:-1.015497)

2014-07-31 14:24:18.966 App[1040:60b] D,-[Prefs getLocation]:81

coordinate:31.2719341228076,34.83940961773958

Solution

  • -(void)rotate:(UIView *)v fromAngle:(float)from angle:(float)angle{
    
        if( from == angle){
            return;
        }
    //to keep rotation in the same direction
        if(abs(toRad(from)-toRad(angle))>=6){
            if(from>angle){
                angle +=360;
                LogTrace(@"add");
            }else {
                angle-=360;
                LogTrace (@"subtract");
            }
        }
    
    
        CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
        animation.fromValue = @(-toRad(from));
        animation.toValue = @(-toRad(angle));
        LogInfo(@"from:%f to:%f",-toRad(from),-toRad(angle));
        animation.duration = 0.0f;
        animation.fillMode = kCAFillModeForwards;
        animation.repeatCount = 0;
        animation.removedOnCompletion = NO;
        animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
        [v.layer setAnchorPoint:CGPointMake(0.5, 0.494)];
        [v.layer addAnimation:animation forKey:@"transform.rotation.z"];
    }