how to Zoom image using CABasicanimation - objective-c

[UIView animateWithDuration:0.5 animations:^{
imageView.frame = self.view.bounds;
} completion:^(BOOL finished) {}];
how can I write this using CABasicanimation.

below is the simple implementation
-(void)StartAnmation {
[subview.layer addAnimation:[self ZoomAnimation] forKey:#"Zoom"];
}
-(CAAnimationGroup *)ZoomAnimation {
CAAnimationGroup *ZoomAnimation = [CAAnimationGroup animation];
CABasicAnimation *In = [self zoomIn];
ZoomAnimation.animations = [NSArray arrayWithObjects: In, nil];
ZoomAnimation.duration = 2.0f;
return ZoomAnimation;
}
-(CABasicAnimation *)zoomIn {
CABasicAnimation *ZoomInAnimation = [CABasicAnimation animationWithKeyPath:#"transform.scale"];
ZoomInAnimation.beginTime = 0.0f;
ZoomInAnimation.fromValue = [NSNumber numberWithFloat:20.0];
ZoomInAnimation.toValue = [NSNumber numberWithFloat:1.0];
ZoomInAnimation.duration = 2.0f;
return ZoomInAnimation;
}

For Zoom images you can done by using UIImageView itself.
Please refer the answer Pinch To Zoom Effect on UIImageView inside scrollView

Related

objective c mask animation

I want to make an animation as below. It is like Angry Birds Game's settings wheel button.
I used images to describe my problem.
I can rotate the wheel
and I can up the image (set_bg.png).
startup position:
end position (after clicked the wheel):
as you see on startup position, I want to hide above wheel but I couldn't do. How can I do this animation?
I tried that code:
on ViewDid:
CALayer *maskLayer = [CALayer layer];
UIImage *maskImage = [UIImage imageNamed:#"set_bg.png"];
maskLayer.contents = (id)maskImage.CGImage;
maskLayer.bounds = CGRectMake(0,0,92,219);
maskLayer.frame =CGRectMake(0,-135,92,219);
btn_setting_bg.layer.mask = maskLayer;
btn_setting_bg.layer.masksToBounds = YES;
on wheel touched:
CGRect position;
CGRect oldBounds;
CGRect newBounds;
CABasicAnimation* animation = [CABasicAnimation animationWithKeyPath:#"transform.rotation.z"];
if(isSubMenuOpened == YES){
animation.fromValue = [NSNumber numberWithFloat:2*M_PI];
animation.toValue = [NSNumber numberWithFloat: 0.0f];
position = CGRectMake(btn_setting_bg.frame.origin.x,btn_settings.frame.origin.y + 6, btn_setting_bg.frame.size.width, btn_setting_bg.frame.size.height);
newBounds = CGRectMake(0,-135,92,219);
oldBounds = CGRectMake(0,0,92,219);
isSubMenuOpened = NO;
}else{
animation.fromValue = [NSNumber numberWithFloat:0.0f];
animation.toValue = [NSNumber numberWithFloat: 2*M_PI];
position = CGRectMake(btn_setting_bg.frame.origin.x,btn_setting_bg.frame.origin.y - btn_setting_bg.frame.size.height -13 + btn_settings.frame.size.height, btn_setting_bg.frame.size.width, btn_setting_bg.frame.size.height);
oldBounds = CGRectMake(0,-135,92,219);
newBounds = CGRectMake(0,0,92,219);
isSubMenuOpened = YES;
// NSLog([NSString stringWithFormat:#"x:%f,y:%f", position.origin.x, position.origin.y]);
}
[UIView animateWithDuration:1.2
delay:0.0
options: UIViewAnimationCurveEaseOut
animations:^{
[btn_setting_bg setFrame:position];
//[btn_setting_bg.layer.mask setFrame:CGRectMake(0,500,92,219)];
}
completion:^(BOOL finished){
CABasicAnimation *animation2 = [CABasicAnimation animationWithKeyPath:#"scale.y"];
animation2.fromValue = [NSValue valueWithCGRect:oldBounds];
animation2.toValue = [NSValue valueWithCGRect:newBounds];
animation2.duration = 1.2f;
btn_setting_bg.layer.mask.frame = newBounds;
// btn_setting_bg.layer.mask.bounds = CGRectMake(0,0,92,219);
[btn_setting_bg.layer.mask addAnimation:animation2 forKey:#"scale.y"];
}];
animation.duration = 1.2f;
animation.repeatCount = 1;
[btn_settings.layer addAnimation:animation forKey:#"SpinAnimation"];
Try animating the alpha property of wheel from 0.0f to 1.0f.
I have solved problem using alpha. It is not what I exactly I want but this is also a good solution.
Thanks to #paulrehkugler and #kate-gregory
Now my code is as simple as:
CGRect position;
CABasicAnimation* animation = [CABasicAnimation animationWithKeyPath:#"transform.rotation.z"];
if(isSubMenuOpened == YES){
animation.fromValue = [NSNumber numberWithFloat:2*M_PI];
animation.toValue = [NSNumber numberWithFloat: 0.0f];
position = CGRectMake(btn_setting_bg.frame.origin.x,btn_settings.frame.origin.y + 6, btn_setting_bg.frame.size.width, btn_setting_bg.frame.size.height);
isSubMenuOpened = NO;
}else{
animation.fromValue = [NSNumber numberWithFloat:0.0f];
animation.toValue = [NSNumber numberWithFloat: 2*M_PI];
position = CGRectMake(btn_setting_bg.frame.origin.x,btn_setting_bg.frame.origin.y - btn_setting_bg.frame.size.height -13 + btn_settings.frame.size.height, btn_setting_bg.frame.size.width, btn_setting_bg.frame.size.height);
isSubMenuOpened = YES;
}
[UIView animateWithDuration:1.2
delay:0.0
options: UIViewAnimationCurveEaseOut
animations:^{
[btn_setting_bg setFrame:position];
}
completion:^(BOOL finished){
}];
animation.duration = 1.2f;
animation.repeatCount = 1;
[btn_settings.layer addAnimation:animation forKey:#"SpinAnimation"];
if(isSubMenuOpened == YES){
[UIView animateWithDuration:3.5 animations:^(void) {
btn_setting_bg.alpha = 1;
}];
}else{
[UIView animateWithDuration:0.8 animations:^(void) {
btn_setting_bg.alpha = 0;
}];
}

Animate Mask in Objective C

I am making an application where I have to show 3 images in a single screen, and when User touch one image then that Image should be shown by Animating and resizing.
So for 1st Step I did Masking of 3 images with 3 different Transparent Mask Image from
How to Mask an UIImageView
And my method is like below
- (UIImageView*) maskedImage:(UIImage *)image withMasked:(UIImage *)maskImage {
UIImageView *imageView = [[UIImageView alloc] initWithImage:image];
CALayer *mask1 = [CALayer layer];
mask1.contents = (id)[maskImage CGImage];
mask1.frame = CGRectMake(0, 0, 1024, 768);
imageView.layer.mask = mask1;
imageView.layer.masksToBounds = YES;
return imageView;
}
And I am calling this as
self.image2 = [UIImage imageNamed:#"screen2Full.png"];
self.mask2 = [UIImage imageNamed:#"maskImage.png"];
self.imageView2 = [self maskedImage:self.image2 withMasked:self.mask2];
[self.completeSingleView addSubview:self.imageView2];
This is working perfectly.
Now for Step 2. Animate the Mask, so that Full Image can be shown. I have googled a lot about this but didn't get success. So Please help me. I just want to know how can we Animate and Resize the Mask Image So that I can view a full Image. My concept is as below.
So finally i got the solution from multiple sites and some own logic and hard work obviously ;). So here is the solution of this
-(void)moveLayer:(CALayer*)layer to:(CGPoint)point
{
// Prepare the animation from the current position to the new position
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:#"position"];
animation.fromValue = [layer valueForKey:#"position"];
animation.toValue = [NSValue valueWithCGPoint:point];
animation.duration = .3;
layer.position = point;
[layer addAnimation:animation forKey:#"position"];
}
-(void)resizeLayer:(CALayer*)layer to:(CGSize)size
{
CGRect oldBounds = layer.bounds;
CGRect newBounds = oldBounds;
newBounds.size = size;
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:#"bounds"];
animation.fromValue = [NSValue valueWithCGRect:oldBounds];
animation.toValue = [NSValue valueWithCGRect:newBounds];
animation.duration = .3;
layer.bounds = newBounds;
[layer addAnimation:animation forKey:#"bounds"];
}
- (UIImageView*) animateMaskImage:(UIImage *)image withMask:(UIImage *)maskImage width:(int )wd andHeight:(int )ht andSize:(CGSize)size andPosition:(CGPoint)pt {
UIImageView *imageView = [[UIImageView alloc] initWithImage:image];
CALayer *mask = [CALayer layer];
mask.contents = (id)[maskImage CGImage];
mask.frame = CGRectMake(0, 0, wd, ht);
//This needs to be place before masking. I don't knwo why. But its working :)
[self resizeLayer:mask to:size];
[self moveLayer:mask to:pt];
imageView.layer.mask = mask;
imageView.layer.masksToBounds = YES;
return imageView;
}
You just need to call this as
[self.imageView1 removeFromSuperview];
self.imageView1 = [self animateMaskedImage:self.image1 withMasked:self.mask1 width:1024 andHeight:768 andSize:CGSizeMake(1024*4, 768*4) andPosition:CGPointMake(1024*2, 768*2)];
[self.completeSingleView addSubview:self.imageView1];

UILabel size change suddenly when parent UIView animate

I want to send a subview out of my super UIView with animation, It works fine but when i tried to change the size during animation any UILabel that i have in my subview suddenly become too small.
here is part of my code
-(void)pushOutScreen:(UIViewController *)pop{
[UIView animateWithDuration:1
delay:0.0
options: UIViewAnimationTransitionFlipFromLeft
animations:^{
CGRect frame = pop.view.frame;
frame.size.height = frame.size.height /4;
frame.size.width = frame.size.width /4;
frame.origin.x = -500;
frame.origin.y = 318;
pop.view.frame = frame;
}
completion:^(BOOL finished){
NSLog(#"Done!");
}];
}
note: any UIButton or UIImage that is inside my subview animated well but i have only problem with UILabel.
UIView animation is not good option for doing this, instead of it try CAKeyframeAnimation. This is sample code for scaling UIView:
- (void) scaleView:(UIView *)popView {
CAKeyframeAnimation *animation = [CAKeyframeAnimation
animationWithKeyPath:#"transform"];
animation.delegate = self;
// CATransform3DMakeScale has 3 parameter (x,y,z)
CATransform3D scale1 = CATransform3DMakeScale(1.0, 1.0, 1);
CATransform3D scale2 = CATransform3DMakeScale(0.2, 0.2, 1);
NSArray *frameValues = [NSArray arrayWithObjects:
[NSValue valueWithCATransform3D:scale1],
[NSValue valueWithCATransform3D:scale2],
nil];
[animation setValues:frameValues];
NSArray *frameTimes = [NSArray arrayWithObjects:
[NSNumber numberWithFloat:0.0],
[NSNumber numberWithFloat:1.0],
nil];
[animation setKeyTimes:frameTimes];
animation.fillMode = kCAFillModeForwards;
animation.removedOnCompletion = NO;
animation.duration = 1.0;
[popView.layer addAnimation:animation forKey:#"popup"];
}
you can use this after you add your UIView as subView then you can call this method as scale it. for push out a sub view with this method you need to use removeFromSubView after the animation finished.
for knowing that when it finished use
-(void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag
{
[subView removeFromSuperview];
}
I hope it be useful!

CGAffineTransformMakeRotation before a CABasicAnimation

I'm performing a rotation of an UIImageView in place first before performing a rotation animation:
// rotate to the left by 90 degrees
someView.transform = CGAffineTransformMakeRotation((-0.5)*M_PI);
Then calling a rotation on the view by 180 degrees... but it seems like it is rotating the image starting from the original position as if it was not initially rotated.
- (void)rotateIndicatorToAngle: (UIView *)view angle: (NSNumber *)angleInDegrees
{
CALayer *layer = view.layer;
CGFloat duration = 5.0;
CGFloat radians = [self ConvertDegreesToRadians: [angleInDegrees floatValue]];
CABasicAnimation* rotationAnimation;
rotationAnimation = [CABasicAnimation animationWithKeyPath:#"transform.rotation.z"];
rotationAnimation.toValue = [NSNumber numberWithFloat: radians];
rotationAnimation.duration = duration;
rotationAnimation.cumulative = YES;
rotationAnimation.repeatCount = 1.0;
rotationAnimation.removedOnCompletion = NO;
rotationAnimation.fillMode = kCAFillModeForwards;
rotationAnimation.timingFunction = [CAMediaTimingFunction
functionWithName:kCAMediaTimingFunctionEaseOut];
[layer addAnimation: rotationAnimation forKey: #"rotationAnimation"];
}
What gives?
rotationAnimation.cumulative = YES;
Have you tried using rotationAnimation.additive = YES; instead of cumulative?
You could use the class methods from UIView to easily animate your view:
[UIView beginAnimation: #"Rotate" context: nil];
[UIView setAnimationDuration: 5.0f];
[UIView setAnimationCurve: UIViewAnimationCurveEaseOut];
CGFloat radians = [self ConvertDegreesToRadians: [angleInDegrees floatValue]];
view.transform = CGAffineTransformMakeRotation(radians);
[UIView commitAnimation];
That's what I'm using most of the time, no need to use layers.
UPDATE: I mean, I find it easier not to use layers in that case, no pejorative value on using layers.

Better way to do UILabel animations in Cocoa Touch?

In the past, when I've wanted to do a nice fade animation from one UILabel text to another, I chuck in the following:
[UIView beginAnimations:#"fade" context:nil];
[UIView setAnimationDuration:0.25];
myLabel.alpha = 0.0;
myLabel.text = #"Different string";
myLabel.alpha = 1.0;
[UIView commitAnimations];
As you can probably tell, the label does a quick fade out, change content, then fades back in.
I've seen some instances in other apps where the text just seems to fade really smoothly - without appearing to fade out and back in quickly.
Is it just me or is there a better way of achieving this?
Thanks.
Ricky.
Hope this helps.
-(void)showButton:(UIButton *)button {
CABasicAnimation *opacityAnimation = [CABasicAnimation animationWithKeyPath:#"opacity"];
opacityAnimation.fromValue = [NSNumber numberWithFloat:0.0f];
opacityAnimation.toValue = [NSNumber numberWithFloat:1.0f];
button.hidden = NO;
[button.layer addAnimation:opacityAnimation
forKey:#"opacity"];
}
-(void)hideButton:(UIButton *)button {
CABasicAnimation *opacityAnimation = [CABasicAnimation animationWithKeyPath:#"opacity"];
opacityAnimation.fromValue = [NSNumber numberWithFloat:1.0f];
opacityAnimation.toValue = [NSNumber numberWithFloat:0.0f];
button.hidden = YES;
[button.layer addAnimation:opacityAnimation
forKey:#"opacity"];
}