I have created Visiting Card which has Front view & back View. When i tap on the front view it should flip the UIView & show the back side of the View.
Here is Code which I am trying:
CATransform3D transform = CATransform3DMakeRotation(M_PI, 0, 1, 0);
transform.m34 = 1.0/700.0;
CABasicAnimation *rotation = [CABasicAnimation animationWithKeyPath:#"transform"];
rotation.fromValue = [NSValue valueWithCATransform3D:CATransform3DIdentity];
rotation.toValue = [NSValue valueWithCATransform3D:transform];
rotation.duration = DURATION;
CABasicAnimation *translation = [CABasicAnimation animationWithKeyPath:#"position"];
translation.fromValue = [NSValue valueWithCGPoint:CGPointMake(self.imageview.center.x,[[self.imageview superview] center].y-45)];
translation.toValue = [NSValue valueWithCGPoint:CGPointMake(_frame.origin.x+_frame.size.width/2,
_frame.origin.y+_frame.size.height/2)];
translation.duration = DURATION;
CABasicAnimation *translation = [CABasicAnimation animationWithKeyPath:#"position"];
translation.fromValue = [NSValue valueWithCGPoint:CGPointMake(self.imageview.center.x,[[self.imageview superview] center].y-45)];
translation.toValue = [NSValue valueWithCGPoint:CGPointMake(_frame.origin.x+_frame.size.width/2,
_frame.origin.y+_frame.size.height/2)];
translation.duration = DURATION;
CAAnimationGroup *group = [CAAnimationGroup animation];
group.animations = #[ translation, rotation ];
group.duration = DURATION;
group.delegate = self;
group.fillMode = kCAFillModeForwards;
group.removedOnCompletion = NO;
[layer addAnimation:group forKey:nil];
Above code works perfectly for single view. How to combine the 2nd view to get flipping from front & back effect.
Using Core Animation
You can add both front and back to a container view. The back view will have a 180 degree rotation around Y and the front will be just normal. Both layers will be single sided (by setting layer.doubleSided = NO;.
Then when you apply the rotation you would animate the rotation of the container view so that both front and back animate at the same time.
UIView transitions
Or you could just use the built in flip animation
transitionFromView:toView:duration:options:completion:
and pass either UIViewAnimationOptionTransitionFlipFromLeft or UIViewAnimationOptionTransitionFlipFromRight for the option.
Related
Recently more and more apps are using new type of transition between views.
It's hard to define it but the transition looks like the preview view is fading out, going lower (downward translation) and scale down a little - all simultanously.
It's really subtle and elegant.
You can observe this transition in slow motion in Facebook app - find somebody's picture on the wall, tap to view it and then drag the fullscreen image down slowly and you will notice that the wall is rising from the back - fading and scaling a little bit. That's the transition.
Transition also envolves statusbar fading.
This transition is also present in Gmail 2.0 when you open settings from the left pane.
I think there is a certain framework or prepared method for this because more and more apps have this implemented.
But maybe I'm also wrong because I see some minor differences in some apps in the transition's trajectory - eg. Gmail uses a little carousel effect, but facebook just scales down to the middle.
Anyway it appears to be a new trend.
I'm looking for some reference or framework or know-how about implementing that sort of transitions.
Thanks for any useful stuff.
Try this link.I think this is the thing you are exactly looking for https://github.com/kentnguyen/KNSemiModalViewController
I first saw it used in the National Geographic apps... have a try with these two methods, the first 'drops it back' the second 'brings it back'. It's worked well for me in the past, just make a few adjustments to suit your needs.
- (void)dropItBack:(id)sender
{
// Position
CABasicAnimation *posAnimation = [CABasicAnimation animationWithKeyPath:#"position"];
posAnimation.toValue = [NSValue valueWithCGPoint:CGPointMake(160, 284)];//center point
// Opacity
CABasicAnimation *opacityAnimation = [CABasicAnimation animationWithKeyPath:#"opacity"];
opacityAnimation.toValue = [NSNumber numberWithFloat:0.5f];
CABasicAnimation *scaleAnimation = [CABasicAnimation animationWithKeyPath:#"transform.scale"];
scaleAnimation.toValue = [NSNumber numberWithDouble:0.8];
// Dramaticism of the Z rotation
// A lower number is more dramatic
float distance = 1000;
CATransform3D trans = CATransform3DIdentity;
trans.m34 = 1.f / -distance;
// Rotate Back
CABasicAnimation *rockBack = [CABasicAnimation animationWithKeyPath:#"transform"];
rockBack.toValue = [NSValue valueWithCATransform3D:CATransform3DRotate(trans, M_PI_4, 1.f, 0.f, 0.f)];
rockBack.beginTime = 0.f;
// Rotate forward
trans.m34 = 0.f;
CABasicAnimation *rockForward = [CABasicAnimation animationWithKeyPath:#"transform"];
rockForward.toValue = [NSValue valueWithCATransform3D:CATransform3DRotate(trans, M_PI_4, -1.f, 0.f, 0.f)];
rockForward.beginTime = 0.25f;
CAAnimationGroup *animationGroup = [CAAnimationGroup animation];
animationGroup.duration = 0.5f;
animationGroup.repeatCount = 0.f;
animationGroup.removedOnCompletion = NO;
animationGroup.autoreverses = NO;
animationGroup.fillMode = kCAFillModeForwards;
animationGroup.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
[animationGroup setAnimations:[NSArray arrayWithObjects:rockBack, rockForward, scaleAnimation, posAnimation, opacityAnimation, nil]];
[self.navigationController.view.layer addAnimation:animationGroup forKey:nil];
popsheet = [UIButton buttonWithType:UIButtonTypeCustom];
[popsheet setBackgroundColor:[UIColor blueColor]];
[popsheet setFrame:CGRectMake(0, 580, 320, 400)];
[popsheet addTarget:self action:#selector(bringItForward:) forControlEvents:UIControlEventTouchUpInside];
[self.tabBarController.view addSubview:popsheet];
[UIView animateWithDuration:0.3 animations:^{
[popsheet setFrame: CGRectMake(0, 180, 320, 400)];
}];
}
- (void)bringItForward:(id)sender
{
// Position
CABasicAnimation *posAnimation = [CABasicAnimation animationWithKeyPath:#"position"];
posAnimation.toValue = [NSValue valueWithCGPoint:CGPointMake(160, 284)];
// Opacity
CABasicAnimation *opacityAnimation = [CABasicAnimation animationWithKeyPath:#"opacity"];
opacityAnimation.toValue = [NSNumber numberWithFloat:1.f];
// Scale
CABasicAnimation *scaleAnimation = [CABasicAnimation animationWithKeyPath:#"transform.scale"];
scaleAnimation.toValue = [NSNumber numberWithDouble:1.f];
// Dramaticism of the Z rotation
// A lower number is more dramatic
float distance = 1000;
CATransform3D trans = CATransform3DIdentity;
trans.m34 = 1.f / distance;
// Rotate back
CABasicAnimation *rockBack = [CABasicAnimation animationWithKeyPath:#"transform"];
rockBack.toValue = [NSValue valueWithCATransform3D:CATransform3DRotate(trans, M_PI_4, 1.f, 0.f, 0.f)];
rockBack.beginTime = 0.f;
// Rotate forward
trans.m34 = 0.f;
CABasicAnimation *rockForward = [CABasicAnimation animationWithKeyPath:#"transform"];
rockForward.toValue = [NSValue valueWithCATransform3D:CATransform3DRotate(trans, M_PI_4, -1.f, 0.f, 0.f)];
rockForward.beginTime = 0.25f;
CAAnimationGroup *animationGroup = [CAAnimationGroup animation];
animationGroup.duration = 0.5f;
animationGroup.repeatCount = 0.f;
animationGroup.removedOnCompletion = NO;
animationGroup.autoreverses = NO;
animationGroup.fillMode = kCAFillModeForwards;
animationGroup.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
[animationGroup setAnimations:[NSArray arrayWithObjects:posAnimation, rockBack, rockForward, opacityAnimation, nil]];
[self.navigationController.view.layer addAnimation:animationGroup forKey:nil];
[UIView animateWithDuration:0.3 animations:^{
[popsheet setFrame: CGRectMake(0, 580, 320, 400)];
}];
}
I think you should try this library:
https://github.com/michaelhenry/MHFacebookImageViewer
well I have a CALayer layer and I would like to move it, with a CADisplaylink. Like :
layer.center=CGPointMake(layer.center.x + 10, layer.center.y + 10);
but I can't use center or position for the layer.Here is my problem, I want to make it move like it was a uiimageview.
To move layer try to use this method
-(void)moveLayer:(CALayer*)layer to:(CGPoint)point{
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:#"position"];
animation.fromValue = [layer valueForKey:#"position"];
animation.toValue = [NSValue valueWithCGPoint:point];
layer.position = point;
[layer addAnimation:animation forKey:#"position"];
}
Any idea why the small image that I move across the screen gets blurry?
While being in motion, the small details in the image become unclear and I think that it is a problem.
CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:#"position"];
anim.fromValue = [NSValue valueWithCGPoint:CGPointMake(px2.x, px2.y)];
anim.toValue = [NSValue valueWithCGPoint:CGPointMake(P3x, P3y)];
anim.duration = 1.5f;
anim.repeatCount =1;
anim.removedOnCompletion = YES;
anim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];
[LA addAnimation:anim forKey:#"position"];
Eventually this was identified as LCD panel lag.
i am applying CABasicAnimation for position property of a layer it is animating well but after animation complete its coming back to original position how to avoid that and to make image to stay in animated position only?
There are a few different ways to solve this. My favorite is to set the object at the end of the animation, and use fromValue instead of toValue to create the animation. You can also set both fromValue and toValue to create this effect. ie
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:#"position"];
animation.duration = 1.0;
animation.fromValue = [NSValue valueWithCGPoint:startPoint];
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];
viewToAnimate.center = endPoint;
[viewToAnimate.layer addAnimation:animation forKey:#"slide"];
The other way to do this is to set yourself as the delegate and implement:
-(void)animationDidStop:(id)sender finished:(BOOL)finished {
viewToAnimate.center = endPoint;
}
You need to set the final position. If you only use the animation fromValue and toValue it will snap back to the original starting point. The animation uses a copy of the view/layer as it "plays" and then the animation will show the original view/layer when it finishes.
If you don't explicitly set it, it will appear to snap back, even though the view/layer never really moved.
startPoint and endPoint are CGPoints and myView is the UIView that is being animated.
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:#"position"];
animation.duration = .3;
animation.fromValue = [NSValue valueWithCGPoint:startPoint];
animation.toValue = [NSValue valueWithCGPoint:endPoint];
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
[myView.layer addAnimation:animation forKey:#"position"];
myView.layer.position = endPoint; // Must set end position, otherwise it jumps back
To set the object at the end of the animation just write the code like this
#import <QuartzCore/QuartzCore.h>
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:#"position"];
animation.duration = 1.0;
animation.fromValue = [NSValue valueWithCGPoint:startPoint];
animation.timingFunction = [CAMediaTimingFunction functionWithName:easing];
animation.fillMode = kCAFillModeForwards; // This line will stop the animation at the end position of animation
animation.autoreverses = NO;
viewToAnimate.center = endPoint;
[viewToAnimate.layer addAnimation:animation forKey:#"slide"];
You can just set removedOnCompletion to NO if you want to preserve the final value. And don't forget to set the fillMode.
Swift 4+
animation.fillMode = .forwards;
animation.isRemovedOnCompletion = false
Objective-C
animation.fillMode = kCAFillModeForwards; //The receiver remains visible in its final state when the animation is completed.
animation.removedOnCompletion = NO;
If you look at the docs for addAnimation:forKey:, it says 'Typically this is implicitly invoked'. In other words, you're not supposed to call it directly. You're actually meant to do the following instead, which is even easier than setting from and to values, you simply set the values directly on the layer:
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:#"opacity"];
animation.duration = .3;
myLayer.actions = #{#"opacity": animation};
myLayer.opacity = 0;
This will fade a layer to zero opacity.
I'm using following code to animate a view. It basically rotates the view by 225 degrees angle.
[viewToOpen.layer removeAllAnimations];
viewToOpen.hidden = NO;
viewToOpen.userInteractionEnabled = NO;
if (viewToOpen.layer.anchorPoint.x != 0.0f) {
viewToOpen.layer.anchorPoint = CGPointMake(0.0f, 0.5f);
viewToOpen.center = CGPointMake(viewToOpen.center.x - viewToOpen.bounds.size.width/2.0f, viewToOpen.center.y);
}
CABasicAnimation *transformAnimation = [CABasicAnimation animationWithKeyPath:#"transform"];
transformAnimation.removedOnCompletion = NO;
transformAnimation.duration = duration;
transformAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
CATransform3D endTransform = CATransform3DMakeAffineTransform(CGAffineTransformMakeRotation(225));
transformAnimation.toValue = [NSValue valueWithCATransform3D:endTransform];
CAAnimationGroup *theGroup = [CAAnimationGroup animation];
theGroup.delegate = self;
theGroup.duration = duration;
[theGroup setValue:[NSNumber numberWithInt:viewToOpen.tag] forKey:#"viewToOpenTag"];
theGroup.animations = [NSArray arrayWithObjects:transformAnimation, nil];
theGroup.removedOnCompletion = NO;
[viewToOpen.layer addAnimation:theGroup forKey:#"flipViewOpen"];
But the problem is that, at the end of animation, the view is coming back to original position. I would like to keep the view in same position even after animation completes. How can I do it?
I believe you're experiencing the same issue as can be seen in this question and this one. You either need to set fillMode to kCAFillModeForwards or set the transform of the layer when the animation has been completed.