[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
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;
}];
}
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];
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!
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.
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"];
}