Background

I needed a wrapper to clean up my animation code. I prefer this to the UIView animateWithDuration because i can run multiple animations and control time and delay of each one independently. I also don’t like how most people use CABasicAnimation.

A common issue is that animations changes the Presentation Layer and not the Model Layer. So button taps for example will be captured where the model layer is not where the button animated to. This utility updates both seamlessly so you have to worry about leaving animations on the stack with:

myAnimation.removeOnCompletion = NO; myAnimation.fillMode = kCAFillModeForwards;

Instead, set the values to the model (updating the UI) and do the animation From the original value to the new value.

id currentValue = [layer valueForKeyPath:keyPath]; CABasicAnimation* animation = [CABasicAnimation animationWithKeyPath:keyPath]; animation.fromValue = currentValue; animation.toValue = toValue; animation.duration = duration; [layer addAnimation:animation forKey:keyPath]; // start animation [layer setValue:toValue forKeyPath:keyPath]; // update the model so the animation doesn't seem to dissapear

If you have multiple animations its easier to group all of them into an animation group if they share similar triggers

CAAnimationGroup* group = [CAAnimationGroup animation]; group.animations = @[myAnimation1, myAnimation2, myAnimation3]; group.duration = 1.5; [layer addAnimation:group forKey:@"animations"];

A note, if your view is added as a child of UIWindow there will be cropping issues before the animation ends for “transform.rotation.x / y”. If that is an issue just make sure its added to a UIView thats on the window thats not animating (this was a fun little issue to debug)

The Utility

To make all of this easier use the HMBasicAnimation utility

source: https://github.com/HelloMihai/HMDevKitObjc/tree/master/Classes/BasicAnimation

or use my CocoaPods : pod 'HMDevKitObjc'

Usage:

import #import "HMBasicAnimation.h";

3D rotate a UIView by degrees [HMBasicAnimation rotate3D:myView.layer toDegreeAngle:45 duration:1.5 delaySeconds:0.5 keyPath:HMBasicAnimation_ROTATION_Y];

to change the X coordinate relatively by 50 points [HMBasicAnimation animate:myView.layer toValue:@50 // @ to be an number object duration:1.5 delaySeconds:0 keyPath:HMBasicAnimation_TRANSLATION_X];

to change to an absolute Y coordinate of 100 points [HMBasicAnimation animate:myView.layer toValue:@100 // @ to be an number object duration:1.5 delaySeconds:0 keyPath:HMBasicAnimation_POSITION_Y];

to chain several animations play with the delay and duration values [HMBasicAnimation animate:myView.layer toValue:@100 duration:1.0 delaySeconds:0 keyPath:HMBasicAnimation_POSITION_Y]; [HMBasicAnimation animate:myView.layer toValue:@150 duration:1.0 delaySeconds:1 keyPath:HMBasicAnimation_POSITION_Y];

rotate with easing [HMBasicAnimation rotate3D:myView.layer toDegreeAngle:50 duration:3 delaySeconds:1 keyPath:HMBasicAnimation_ROTATION_Y withEase:HMBasicAnimation_EASING_EASE_IN];

other properties that can be manipulated (add your own)

NOTE: translation is relative the current x,y,z value and not an absolute movement HMBasicAnimation_OPACITY HMBasicAnimation_ROTATION HMBasicAnimation_ROTATION_Y HMBasicAnimation_ROTATION_X HMBasicAnimation_ROTATION_Z HMBasicAnimation_SCALE_X HMBasicAnimation_SCALE_Y HMBasicAnimation_SCALE_Z HMBasicAnimation_TRANSLATION_X // relative change from current x HMBasicAnimation_TRANSLATION_Y // relative change from current y HMBasicAnimation_TRANSLATION_Z // relative change from current z HMBasicAnimation_POSITION_X // center is registration point HMBasicAnimation_POSITION_Y // center is registration point

other easing methods to use HMBasicAnimation_EASING_NONE HMBasicAnimation_EASING_LINEAR HMBasicAnimation_EASING_EASE_IN HMBasicAnimation_EASING_EASE_OUT HMBasicAnimation_EASING_EASE_IN_OUT HMBasicAnimation_EASING_DEFAULT