CATransform3D Animation Set X Axis - ios

I have a CATransform3D Animation designed to replace the Push animation currently being used in my app. Currently, it rotates as if the X axis were in the centre of the layer/view. However, I want the X axis to be at the edge of the screen so it flips out of the screen. My current code is: -
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.5];
CATransform3D rotationAndPerspectiveTransform = CATransform3DIdentity;
rotationAndPerspectiveTransform.m34 = 1.0 / 500;
rotationAndPerspectiveTransform = CATransform3DRotate(rotationAndPerspectiveTransform, 1.57, 0, 1, 0);
self.view.layer.transform = rotationAndPerspectiveTransform;
[UIView commitAnimations];
I'm new to Core Graphics and such, so any pointers, tips, where I'm going wrong will be greatly appreciated!

You should change the anchorPoint of the layer. Use the following piece of code before beginAnimations:context: method.
CGRect frame = self.view.layer.frame;
self.view.layer.anchorPoint = CGPointMake(1.f, 0.5f);
self.view.layer.frame = frame;
This will change the anchorPoint of the layer without changing the layer position. The rotation animation will be done around the axis that passes from the anchor point.

Related

Scaling down the width of a view after doing rotation by using CGAffineTransformScale

I have drawn a view(black rectangle) straight to the x-axis then I am applying some rotation by using CGAffineTransformMakeRotation.Please see image 1 after rotation.
After this I need to reduce the width from that rotated position.
For that I am using CGAffineTransformScale but image is not scaling down along the slope.Please see image 2.
If I change width from bound property then it works fine.
Any idea why CGAffineTransformScale behaves like that.
Below is my sample code.
**__block CGAffineTransform rotationTransform;
rotationTransform = CGAffineTransformMakeRotation(angle);
lineview.transform = rotationTransform;
[UIView animateWithDuration:10 animations:^{
CGAffineTransform finalTransform = CGAffineTransformScale(lineview.transform, 0.4, 1);
lineview.transform = finalTransform;
} completion:^(BOOL finished) {
}];
Try this to move the frame and change the width :)
VIEW.frame = CGRectMake(0,39, 320, 111);
This is the format
CGRectMake(CGFloat x, CGFloat y, CGFloat width, CGFloat height)

UIImageview rotation animation

I want to apply an animation to two UIImageViews. The idea is for image one to flip horizontally by 90 degrees and then image two to complete the rotation. Think of it as a coin spinning: Head side (image one) faces forward -> turn 90 degrees -> Tail side (image two) rotates to face forward. I can do the first half of the animation but I am stuck on the second.
[UIView animateWithDuration:1.0f animations:^{
image1.transform = CGAffineTransformMakeScale(-0.01, 1);
} completion: ^(BOOL finished) {
// How can I make image 2 to rotate out as if it initially was already rotated by 90 degrees?
}];
for flipping animation, there a animation option called UIViewAnimationOptionTransitionFlipFromRight, use it with the UIView's animation method for example, like below for example
[UIView transitionWithView:myImageView //with first image
duration:animationDuration
options:UIViewAnimationOptionTransitionFlipFromRight
animations:^{
myImageView.image = toImage; //to next image
} completion:^(BOOL finished) {
//completion actions after flipped
}];
there are other animation options also there, like FromLeft,
FromTop,FromBottom use any one to your requirement
Take a look at this question about flipping a UIView in 3D using CATransform3D.
Simple Core Animations 3D transform of UIView
The answer:
CATransform3D rotationAndPerspectiveTransform = CATransform3DIdentity;
rotationAndPerspectiveTransform.m34 = 1.0 / -1000.0;
rotationAndPerspectiveTransform = CATransform3DRotate(rotationAndPerspectiveTransform, M_PI * 0.6, 1.0f, 0.0f, 0.0f);
[UIView animateWithDuration:1.0 animations:^{
self.someView.layer.anchorPoint = CGPointMake(0.5, 0);
self.someView.layer.transform = rotationAndPerspectiveTransform;
} completion:^(BOOL finished){
// code to be executed when flip is completed
}];

How to move uiview on this trajectory

Can me explane how I can rotate image use anchor point like
https://www.dropbox.com/s/vh3h5cr1mkdbfh3/ex_image2.JPG
on .m
#import <QuartzCore/QuartzCore.h>
on .h
[UIView animateWithDuration:0.7f
delay:0
options:UIViewAnimationOptionCurveEaseOut
animations:^
{
self.center = position;
self.layer.anchorPoint = CGPointMake(-1, 0);
self.transform = CGAffineTransformMakeRotation(-5);
}
completion:^(BOOL completed){
}];
When I use this code I have something like that
https://www.dropbox.com/s/v87abux9dqm4y0p/ex_image1.JPG
When you apply a rotation transform to a layer, the rotation occurs around the anchor point.
So set the layer's anchor point to (0.0, 0.0) first.
self.layer.anchorPoint = CGPointMake(0.0f, 0.0f);
Then you can just rotate the view and the rotation will occur around the anchor point, (0.0, 0.0).
[UIView animateWithDuration:2.0f animations:^{
self.transform = CGAffineTransformMakeRotation(3.1415f);
}];
The code will rotate the view one whole time in the way you have pictured.
You can check out the section titled "Anchor Points Affect Geometric Manipulations" in Apple's "Core Animation Programming Guide" for more information.

How to animate UIImageViews like hatch doors opening

I'm trying to create an animation that would look like 2 french doors (or 2 hatch doors) opening towards the user.
I tried using the built in UIViewAnimationOptionTransitionFlipFromRight transition, but the origin of the transition seems to be the center of the UIImageView rather than the left edge. Basically I have 2 UIImageViews that each fill have the screen. I would like the animation to look like the UIImageViews are lifting from the center of the screen to the edges.
[UIView transitionWithView:leftView
duration:1.0
options:UIViewAnimationOptionTransitionFlipFromRight
animations:^ { leftView.alpha = 0; }
completion:^(BOOL finished) {
[leftView removeFromSuperview];
}];
Has anyone done something like this before? Any help would be awesome!
UPDATE:
Working code thanks to Nick Lockwood
leftView.layer.anchorPoint = CGPointMake(0, 0.5); // hinge around the left edge
leftView.frame = CGRectMake(0, 0, 160, 460); //reset view position
rightView.layer.anchorPoint = CGPointMake(1.0, 0.5); //hinge around the right edge
rightView.frame = CGRectMake(160, 0, 160, 460); //reset view position
[UIView animateWithDuration:0.75 animations:^{
CATransform3D leftTransform = CATransform3DIdentity;
leftTransform.m34 = -1.0f/500; //dark magic to set the 3D perspective
leftTransform = CATransform3DRotate(leftTransform, -M_PI_2, 0, 1, 0);
leftView.layer.transform = leftTransform;
CATransform3D rightTransform = CATransform3DIdentity;
rightTransform.m34 = -1.0f/500; //dark magic to set the 3D perspective
rightTransform = CATransform3DRotate(rightTransform, M_PI_2, 0, 1, 0);
rightView.layer.transform = rightTransform;
}];
First add the QuartzCore library to your project and #import <QuartzCore/QuartzCore.h>
Every view has a layer property with sub-properties that are animatable. This is where you'll find all the really cool stuff when it comes to animation capabilities (I suggest reading up on the CALayer class properties you can set - it will blow your mind - dynamic soft drop shadows on any view?)
Anyway, back on topic. To rotate your doors open in 3D, first position them as if they were closed, so with each door filling half the screen.
Now set their view.layer.anchorPoint properties as follows
leftDoorView.layer.anchorPoint = CGPoint(0, 0.5); // hinge around the left edge
rightDoorView.layer.anchorPoint = CGPoint(1.0, 0.5); // hinge around the right edge
Now apply the following animation
[UIView animateWithDuration:0.5 animations:^{
CATransform3D leftTransform = CATransform3DIdentity;
leftTransform.m34 = -1.0f/500; //dark magic to set the 3D perspective
leftTransform = CATransform3DRotate(leftTransform, M_PI_2, 0, 1, 0); //rotate 90 degrees about the Y axis
leftDoorView.layer.transform = leftTransform;
//do the same thing but mirrored for the right door, that probably just means using -M_PI_2 for the angle. If you don't know what PI is, Google "radians"
}];
And that should do it.
DISCLAIMER: I've not actually tested this, so the angles may be backwards, and the perspective may be screwy, etc. but it should be a good start at least.
UPDATE: Curiosity got the better of me. Here is fully working code (this assumes that the left and right doors are laid out in the closed position in the nib file):
- (void)viewDidLoad
{
[super viewDidLoad];
leftDoorView.layer.anchorPoint = CGPointMake(0, 0.5); // hinge around the left edge
leftDoorView.center = CGPointMake(0.0, self.view.bounds.size.height/2.0); //compensate for anchor offset
rightDoorView.layer.anchorPoint = CGPointMake(1.0, 0.5); // hinge around the right edge
rightDoorView.center = CGPointMake(self.view.bounds.size.width,self.view.bounds.size.height/2.0); //compensate for anchor offset
}
- (IBAction)open
{
CATransform3D transform = CATransform3DIdentity;
transform.m34 = -1.0f/500;
leftDoorView.layer.transform = transform;
rightDoorView.layer.transform = transform;
[UIView animateWithDuration:0.5 animations:^{
leftDoorView.layer.transform = CATransform3DRotate(transform, M_PI_2, 0, 1, 0);
rightDoorView.layer.transform = CATransform3DRotate(transform, -M_PI_2, 0, 1, 0);
}];
}
- (IBAction)close
{
[UIView animateWithDuration:0.5 animations:^{
CATransform3D transform = CATransform3DIdentity;
transform.m34 = -1.0f/500;
leftDoorView.layer.transform = transform;
rightDoorView.layer.transform = transform;
}];
}

how can I interrupt/stop animation when I rotate?

For example, I use the animation in landscape status, duration is 5.0s, from status A to B; in the middle of the 5.0s, I may rotate the iPad from landscape to portrait. I want the animation stopped and make the UI status to C after I rotated.
I'm not sure my question is clear.
How can I do that?
my animation code:
- (void)moveImage:(UIImageView *)image duration:(NSTimeInterval)duration x:(NSNumber*)dx y:(NSNumber*)dy
{
// Setup the animation
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:duration];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationBeginsFromCurrentState:YES];
// The transform matrix
float fx = [dx floatValue];
float fy = [dy floatValue];
CGAffineTransform transform = CGAffineTransformMakeTranslation(fx, fy);
//CGAffineTransform transform = CGAffineTransformMakeRotation(0.4);
//CGAffineTransform transform = CGAffineTransformMakeScale(2.0, 2.0);
image.transform = transform;
// Commit the changes
[UIView commitAnimations];
}
Starting and Stopping Explicit Animations has a section on starting and stopping core animations
willRotateToInterfaceOrientation:duration notifies you when the rotation begins.
So all have to do is 1) from 2)

Resources