I'm trying to create a kind of 'flip' animation that rotates a UIView 180 degrees around each axis, however, I am having trouble getting the desired effect. Here's what I've got so far:
[UIView animateWithDuration:0.5 delay:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
CATransform3D tX= CATransform3DIdentity;
tX.m34 = 1.0 / -500;
CATransform3D tY= CATransform3DIdentity;
tY.m34 = 1.0 / -500;
CATransform3D tZ= CATransform3DIdentity;
tZ.m34 = 1.0 / -500;
tX = CATransform3DRotate(tX, M_PI, 1.0f, 0.0f, 0.0f);
tY = CATransform3DRotate(tY, M_PI, 0.0f, 1.0f, 0.0f);
tZ = CATransform3DRotate(tZ, M_PI, 0.0f, 0.0f, 1.0f);
self.flipView.layer.transform = CATransform3DConcat(tX, CATransform3DConcat(tY, tZ));
}
This however, doesn't appear to perform any animations, as if they are canceling eachother out. Seems like this should be a pretty straightforward task, but I can't seem to figure out how to combine each of those 3 animation conditions. Any help greatly appreciated! thanks
Rotating by a half-rotation (180° or π radians) about each of the three axes does, in total, result in no change (the concatenation of the three rotation transforms results in the identity transform).
Try rotating about just one axis to see what that does.
Related
In my iOS project , I am using CLImageEditor. I have to add straighten effect in to that. Can any one please help me how to make "straighten" effect?
Add QuartzCore.framework
#import <QuartzCore/QuartzCore.h>
Here is some basic code for rotation, perspective and scale.
CALayer *layer = myView.layer;
CATransform3D rotationAndPerspectiveTransform = CATransform3DIdentity;
// Rotate
rotationAndPerspectiveTransform = CATransform3DRotate(rotationAndPerspectiveTransform, rotate, 0.0f, 0.0f, 1.0f);
// Perspective
// mysterious multiplier m34
// m34 = -1.0 / 500, 500 being somewhat the size of the view
rotationAndPerspectiveTransform.m34 = .02;
rotationAndPerspectiveTransform = CATransform3DTranslate(rotationAndPerspectiveTransform, 0.0f , 0.0f, translate);
// Scale
rotationAndPerspectiveTransform = CATransform3DScale(rotationAndPerspectiveTransform, scale, scale, 1.0f);
layer.transform = rotationAndPerspectiveTransform;
I am trying to rotate the Image around the lower right edge.
Now it rotates around the center.
CATransform3D transform = CATransform3DIdentity;
transform.m34 = 1.0f/-800.0f; // perspective
transform = CATransform3DRotate(transform, (M_PI * 90), 0.0f, 0.0f, 1.0f);
if (animation)
{
[UIView animateWithDuration:0.9
animations:^{
[[_sendRecordView layer] setTransform:transform];
} completion:NULL];
}
else
{
[[_sendRecordView layer] setTransform:transform];
}
You need to set this:
[_sendRecordView layer].anchorPoint = CGPointMake(X, Y);
where X and Y are the desired lower right edge point.
EDIT:
By default a view spins around the center because the anchorPoint is in that position.
I have done this before but I somehow don't get this to work. I have googled a bit but none of the answers I have found solve it.
I am just trying to add a small view to my self.view and would like to rotate this added subview on its y-axis with perspective.
Here is the code:
UIView *rotatingView = [[UIView alloc] initWithFrame:(CGRect){{40.0f, 50.0f}, 50.0f, 50.0f}];
rotatingView.backgroundColor = [UIColor lightGrayColor];
CATransform3D transform = CATransform3DIdentity;
transform.m34 = 1.0 / -500.0;
transform = CATransform3DMakeRotation(DEGREES_RADIANS(20.0f), 0.0f, 1.0f, 0.0f);
rotatingView.layer.transform = transform;
[self.view addSubview:rotatingView];
It is plain simple. But there is absolutely no perspective whatsoever. I expect to see a "skewed" view so that it gives the perspective that it is rotated on the y-axis, but to no avail.
I have even tried setting zPosition and the anchorPoint but none helps.
I have a feeling that I am just missing just something very simple. How I did it before has slipped out of my mind.
You are overwriting the transform that has perspective with the rotation transform
// Define the "transform" variable here
CATransform3D transform = CATransform3DIdentity;
transform.m34 = 1.0 / -500.0;
// assign a new transform to it here
transform = CATransform3DMakeRotation(DEGREES_RADIANS(20.0f), 0.0f, 1.0f, 0.0f);
You should probably be using CATransform3DRotate instead:
transform = CATransform3DRotate(transform, DEGREES_RADIANS(20.0f), 0.0f, 1.0f, 0.0f);
I'm trying to rotate an image around the center of a view using sliders, one for x, y and Z planes. I would like the image to rotate inside it's framed boundaries (700X700) but for some reason it rotates around the edges of the frame. I tried resetting the anchor point but that doesn't seem to do anything. here's the code to rotate it around the Y axis; you'll notice the anchor point section commented out - it wasn't having any affect at all. Any idea of what i'm doing wrong?
float angleYDeg = self.ySlider.value;
float angleYRad = (angleYDeg / 180.0) * M_PI;
// Disable Animation
[CATransaction begin];
[CATransaction setValue:[NSNumber numberWithBool:YES]
forKey:kCATransactionDisableActions];
// Get Layers
CALayer *containerLayer = [[self.imageView.layer sublayers] objectAtIndex:0];
CALayer *holder = [containerLayer valueForKey:#"__holderLayer"];
//CGPoint anchor = holder.anchorPoint;
//anchor.y = self.imageView.frame.size.height/2;
//holder.anchorPoint = anchor;
// Update xAngle Value
[containerLayer setValue:[NSNumber numberWithFloat:angleYRad] forKey:#"__angleY"];
// Apply rotations
CGFloat angleX = [[containerLayer valueForKey:#"__angleX"]floatValue];
CATransform3D holderTransform = CATransform3DMakeRotation( angleX, 1.0f, 0.0f, 0.0f);
holderTransform = CATransform3DRotate(holderTransform, angleYRad, 0.0f, 1.0f, 0.0f);
holder.transform = holderTransform;
[CATransaction commit];
// Update Label
self.yValueLabel.text = [NSString stringWithFormat:#"%4.0fº", angleYDeg];
I'm not sure the exact answer to your question as I can't figure out where it's going wrong in the code. By default things should be rotating around the center. I wrote a demo app that shows how to change the rotation for all the axis using a UISlider. I've posted it on github here: https://github.com/perlmunger/AllAxis.git . Here is the gist of the code, though:
- (IBAction)sliderDidChange:(id)sender
{
[self setTransforms];
}
- (void)setTransforms
{
CGFloat x = [_xSlider value];
CGFloat y = [_ySlider value];
CGFloat z = [_zSlider value];
CATransform3D transform = CATransform3DIdentity;
transform.m34 = 1.0f/-800.0f; // perspective
CGFloat rotationValue = x * kRotationMaxInDegrees;
transform = CATransform3DRotate(transform,
degreesToRadians(rotationValue), 1.0f, 0.0f, 0.0f);
rotationValue = y * kRotationMaxInDegrees;
transform = CATransform3DRotate(transform,
degreesToRadians(rotationValue), 0.0f, 1.0f, 0.0f);
rotationValue = z * kRotationMaxInDegrees;
transform = CATransform3DRotate(transform,
degreesToRadians(rotationValue), 0.0f, 0.0f, 1.0f);
[[_rotationView layer] setTransform:transform];
}
This code builds up a collective transform that you apply to the view's layer on each change to any slider.
Doing consecutive transforms can often go awry. When you transform the angleX, the AngleY transform will then be executed based on the new coordinate system. Basically all the transforms are done relative to the "model" or object.
Most people usually expect the transforms to be made relative to the camera system, or as we are looking at the view. Its likely that the results you want are going to be obtained by reversing the order of the transforms like this:
// Apply rotations
CGFloat angleX = [[containerLayer valueForKey:#"__angleX"]floatValue];
CATransform3D holderTransform = CATransform3DMakeRotation( angleYRad, 0.0f, 1.0f, 0.0f);
holderTransform = CATransform3DRotate(holderTransform, angleX, 1.0f, 0.0f, 0.0f);
holder.transform = holderTransform;
[CATransaction commit];
It might help if you think of it as a lifo system (though its not!) if you are considering all moves based on camera coordinates instead of the model's coordinates.
I am trying to get the pitch from CMMotion's attitude and make AVCaptureVideoPreviewLayer transform with pitch angle using CATransform3D. Something like this:
CATransform3D transform = CATransform3DIdentity;
float zDistance = 850;
transform.m34 = 1.0 / -zDistance;
transform = CATransform3DRotate(transform, -_pitch, 1.0f, 0.0f, 0.0f);
transform = CATransform3DScale(transform, 0.5, 0.5, 0.0);
[_videoPreviewLayer setTransform:transform];
However, the transformed AVCaptureVideoPreviewLayer is so slow and it takes around 10 seconds to be transformed. Is there any suggestion to improve the preview layer with 3D transformation more smooth?
Thanks a lot!