
It's a fact that animation can be considered as somewhat less if we come to the functionality part of App.
Again, these elements definitely provide cool effects to make the app feel amazing.
I am going to cover how to use UIView Animations in a curve path.I have shared a small portion of code regarding animating a View or Image in a curve path along with source code.
This tutorial is an example or a hint for the developers that must be helpful to implement this stuff in their project without any issues.
Create Project:
Create a new project in Xcode: File\New\New Project. Pick the Single View Application template and call it CurvePath Animation.
Don't forget to check ARC and Storyboard. Even if in this tutorial we won’t be focusing on these new technologies, it is a good way to come across the new ideas.
-Create a new file (File\New\New File)
- Choose the iOS\Cocoa Touch\Objective-C category template.
Enter “Animations” for the Category and “UIView” for Category on.
#import <UIKit/UIKit.h>
@interface UIView(Animations){
}
-(void)moveTo:(CGPoint)destination duration:(float)secs
option:(UIViewAnimationOptions)option;
-(void)addSubviewWithFadeAnimation:(UIView*)view
duration:(float)secs option:(UIViewAnimationOptions)option;
- (void) removeWithSinkAnimation:(int)steps;
- (void) removeWithSinkAnimationRotateTimer:(NSTimer*) timer;
-(void)moveSpriteInaCurvePathTo:(CGPoint)endPoint
duration:(float)secs sprite:(UIImage*)imageToAnimate
View:(UIButton*)imageViewForAnimation;
-(void)animateSpriteInaCurve:(UIButton*)sprite;
@end
#import "UIView+Animations.h"
#import <QuartzCore/QuartzCore.h>
@implementation UIView (Animation)
-(void)moveTo:(CGPoint)destination
duration:(float)secs option:(UIViewAnimationOptions)option
{
[UIView animateWithDuration:secs delay:0.0 options:option
animations:^{
self.frame=CGRectMake(destination.x,destination.y,self.frame.size.width, self.frame.size.height);
}
completion:^(BOOL finished){
[self removeFromSuperview];
}];
}
// add with a fade-in effect
-(void)addSubviewWithFadeAnimation:(UIView*)view
duration:(float)secs option:(UIViewAnimationOptions)option
{
view.alpha = 0.0; // make the view transparent
[self addSubview:view]; // add it
[UIView animateWithDuration:secs delay:0.0 options:option
animations:^{view.alpha = 1.0;}
completion:nil]; // animate the return to visible
}
// remove self making it "drain" from the sink!
- (void) removeWithSinkAnimation:(int)steps
{
NSTimer *timer;
if (steps > 0 && steps < 100) // just to avoid too much steps
self.tag = steps;
else
self.tag = 50;
timer = [NSTimer scheduledTimerWithTimeInterval:0.05 target:self selector:@selector(removeWithSinkAnimationRotateTimer:) userInfo:nil repeats:YES];
}
-(void) removeWithSinkAnimationRotateTimer:(NSTimer*) timer
{
CGAffineTransform trans = CGAffineTransformRotate(CGAffineTransformScale(self.transform, 0.9, 0.9),0.314);
self.transform = trans;
self.alpha = self.alpha * 0.98;
self.tag = self.tag - 1;
if (self.tag <= 0)
{
[timer invalidate];
[self removeFromSuperview];
}
}
-(void)moveSpriteInaCurvePathTo:(CGPoint)endPoint
duration:(float)secs sprite:(UIImage*)imageToAnimate View:(UIButton*)imageViewForAnimation{
imageViewForAnimation.hidden=NO;
imageViewForAnimation.alpha = 1.0f;
CGRect imageFrame = imageViewForAnimation.frame;
//Your image frame.origin from where the animation need to get start
CGPoint viewOrigin = imageViewForAnimation.frame.origin;
viewOrigin.y = viewOrigin.y + imageFrame.size.height / 2.0f;
viewOrigin.x = viewOrigin.x + imageFrame.size.width / 2.0f;
imageViewForAnimation.frame = imageFrame;
imageViewForAnimation.layer.position = viewOrigin;
[CATransaction begin]; {
[CATransaction setCompletionBlock:^{
[imageViewForAnimation.layer removeAllAnimations];
[imageViewForAnimation removeFromSuperview];
}];
// Set up fade out effect
CABasicAnimation *fadeOutAnimation = [CABasicAnimation animationWithKeyPath:@"opacity"];
[fadeOutAnimation setToValue:[NSNumber numberWithFloat:0.3]];
fadeOutAnimation.fillMode = kCAFillModeForwards;
fadeOutAnimation.removedOnCompletion = NO;
// Set up scaling
CABasicAnimation *resizeAnimation = [CABasicAnimation animationWithKeyPath:@"bounds.size"];
[resizeAnimation setToValue:[NSValue valueWithCGSize:CGSizeMake(10.0f, imageFrame.size.height * (10.0f / imageFrame.size.width))]];
resizeAnimation.fillMode = kCAFillModeForwards;
resizeAnimation.removedOnCompletion = NO;
// Set up path movement
CAKeyframeAnimation *pathAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
pathAnimation.calculationMode = kCAAnimationPaced;
pathAnimation.fillMode = kCAFillModeForwards;
pathAnimation.removedOnCompletion = NO;
//Setting Endpoint of the animation
//CGPoint endPoint = CGPointMake(480.0f - 30.0f, 40.0f);
//to end animation in last tab use
//CGPoint endPoint = CGPointMake( 320-40.0f, 480.0f);
CGMutablePathRef curvedPath = CGPathCreateMutable();
CGPathMoveToPoint(curvedPath, NULL, viewOrigin.x, viewOrigin.y);
CGPathAddCurveToPoint(curvedPath, NULL, endPoint.x, viewOrigin.y, endPoint.x, viewOrigin.y, endPoint.x, endPoint.y);
pathAnimation.path = curvedPath;
CGPathRelease(curvedPath);
CAAnimationGroup *group = [CAAnimationGroup animation];
group.fillMode = kCAFillModeForwards;
group.removedOnCompletion = NO;
[group setAnimations:[NSArray arrayWithObjects:fadeOutAnimation, pathAnimation, resizeAnimation, nil]];
group.duration = secs;
group.delegate = self;
[group setValue:imageViewForAnimation forKey:@"imageViewBeingAnimated"];
[imageViewForAnimation.layer addAnimation:group forKey:@"savingAnimation"];
} [CATransaction commit];
}
-(void)callBackAnimationCurve:(UIButton*)sprite{
UIBezierPath *movePath = [UIBezierPath bezierPath];
[movePath moveToPoint:sprite.center];
[movePath addQuadCurveToPoint:CGPointMake(192,10)
controlPoint:CGPointMake(360,150)];
CAKeyframeAnimation *moveAnim = [CAKeyframeAnimation animationWithKeyPath:@"position"];
moveAnim.path = movePath.CGPath;
moveAnim.removedOnCompletion = YES;
CABasicAnimation *scaleAnim = [CABasicAnimation animationWithKeyPath:@"transform"];
scaleAnim.fromValue = [NSValue valueWithCATransform3D:CATransform3DIdentity];
scaleAnim.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(0.1, 0.1, 1.0)];
scaleAnim.removedOnCompletion =YES;
CABasicAnimation *opacityAnim = [CABasicAnimation animationWithKeyPath:@"alpha"];
opacityAnim.fromValue = [NSNumber numberWithFloat:1.0];
opacityAnim.toValue = [NSNumber numberWithFloat:0.1];
opacityAnim.removedOnCompletion = YES;
CAAnimationGroup *animGroup = [CAAnimationGroup animation];
animGroup.animations = [NSArray arrayWithObjects:moveAnim,scaleAnim, opacityAnim, nil];
animGroup.duration = 3.5;
[sprite.layer addAnimation:animGroup forKey:nil];
}
-(void)animateSpriteInaCurve:(UIButton*)sprite{
[CATransaction begin]; {
[CATransaction setCompletionBlock:^{
[sprite.layer removeAllAnimations];
[sprite removeFromSuperview];
}];
[self callBackAnimationCurve:sprite];
} [CATransaction commit];
}
@end
#import <UIKit/UIKit.h>
#import "UIView+Animations.h"
@interface ViewController : UIViewController{
__weak IBOutlet UIButton *MoveSprite;
NSMutableArray *curvesList;
__weak IBOutlet UIImageView *BasketView;
NSTimer *timer;
}
-(void)animateSpriteCurvePath2:(id)sender;
-(void)MoveSpriteTo:(id)sender;
-(void)moveSpriteInaCurvePath:(id)sender;
-(IBAction)AnimateSprite:(id)sender;
-(IBAction)StopAnimation:(id)sender;
@end
My objective is to animate balloon as sprite from basket towards upward direction in a curve path.
#import "ViewController.h"
@interface ViewController ( )
@property (weak, nonatomic) IBOutlet UIButton *nextpage;
@end
@implementation ViewController
static int curveValues[] = {
UIViewAnimationOptionCurveEaseInOut,
UIViewAnimationOptionCurveEaseIn,
UIViewAnimationOptionCurveEaseOut,
UIViewAnimationOptionCurveLinear
};
- (IBAction)MoveSpriteTo:(id)sender {
UIButton *movingButton=[UIButton buttonWithType:UIButtonTypeCustom];
[movingButton setImage:[UIImage imageNamed:@"sprite.png"] forState:NO];
movingButton.frame=CGRectMake(BasketView.frame.origin.x+90,
BasketView.frame.origin.y-40,40,88);
[self.view addSubview:movingButton];
[movingButton moveTo:
CGPointMake(self.view.frame.origin.x+120,self.view.frame.origin.y+28) duration:3.0 option:curveValues[0]];
}
-(void)moveSpriteInaCurvePath:(id)sender{
UIButton *movingButton=[UIButton buttonWithType:UIButtonTypeCustom];
movingButton.frame=CGRectMake(BasketView.frame.origin.x+90 ,BasketView.frame.origin.y-40,40,88);
[movingButton setImage:[UIImage imageNamed:@"sprite.png"] forState:NO];
[self.view addSubview:movingButton];
movingButton.hidden=YES;
[movingButton moveSpriteInaCurvePathTo:CGPointMake(40,20) duration:2.0 sprite:[UIImage imageNamed:@"sprite.png"] View:movingButton];
}
- (void)animateSpriteCurvePath2:(id)sender{
UIButton *movingButton=[UIButton buttonWithType:UIButtonTypeCustom];
[movingButton setImage:[UIImage imageNamed:@"sprite.png"] forState:NO];
movingButton.frame=CGRectMake(BasketView.frame.origin.x+90,BasketView.frame.origin.y-40,40,88);
[self.view addSubview:movingButton];
[movingButton animateSpriteInaCurve:movingButton];
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
curvesList = [[NSMutableArray alloc] initWithObjects:@"EaseInOut",@"EaseIn",@"EaseOut",@"Linear", nil];
}
-(void)callBackAnimation{
[self moveSpriteInaCurvePath:nil];
[self MoveSpriteTo:nil];
[self animateSpriteCurvePath2:nil];
}
-(IBAction)AnimateSprite:(id)sender{
if (timer==nil){
timer=[NSTimer scheduledTimerWithTimeInterval:0.2 target:self selector:@selector(callBackAnimation) userInfo:nil repeats:YES];
}
}
-(IBAction)StopAnimation:(id)sender{
if (timer!=nil)
[timer invalidate];
timer=nil;
}
}
@end
Hope,it will help you .Cheers :)

curvepath_animation.zip |