Understanding CATransform3D - uiview

I'm playing with CATransform3DMakeRotation in a UIView, and I'm trying to do a 45ยบ, transform like it's laying backwards:
This is the "code" I have, but clearly doesn't do it.
CATransform3D _tr = CATransform3DMakeRotation(3.14/4, 1, 0, 0);
view.layer.transform = _tr;
please help me understand the params.
Thanks.

Basically, your code is correct, but to get the perspective effect, you need to set the sublayerTransform of the superview's layer to something like this:
CATransform3D perspectiveTransform = CATransform3DIdentity;
perspectiveTransform.m34 = 1.0 / -850;
myView.layer.sublayerTransform = perspectiveTransform;
You can experiment with different values for different amounts of distortion.

Related

Making two transformation changes (scale, rotation) in iOS

I'm trying to do the following transformation changes but only one seems to work: -
self.image1.transform = CGAffineTransformMakeRotation(-0.1);
self.image1.transform = CGAffineTransformMakeScale(1.1, 1.1);
Only the first transformation works, what do I need to do make both changes work?
When using CGAffineTransformMake... you are creating a new transformation. So in your code you overwrite the Rotation with the Scale transformation.
CGAffineTransform transform = CGAffineTransformMakeRotation(-0.1);
transform = CGAffineTransformScale(transform, 1.1, 1.1);
self.image1.transform = transform;

Changing the CALayer anchor point

Changing the anchor point of a CALayer after a CATransform3dRotate gives weird results. I think the problem is, anchorPoint property is set on the previous state (no transform) of layer not the current state (after transform) of the layer.
Is there a way to change the anchorPoint of a CALayer's current state??
Code for Transform:
CATransform3D transform = CATransform3DIdentity;
transform.m34 = -(1.0/800.0);
videoPlayerView.layer.zPosition = 100;
videoPlayerView.layer.transform = CATransform3DRotate(transform, (30*M_PI)/180, 1.0f, 0.0f, 0.0f);
Code to change the anchor Point
if(videoPlayerView.layer.anchorPoint.x != 0.0)
{
videoPlayerView.layer.anchorPoint = CGPointMake(0.0, 0.5);
videoPlayerView.layer.position = CGPointMake(videoPlayerView.layer.frame.origin.x - videoPlayerView.layer.frame.size.width/2,videoPlayerView.layer.position.y);
}
Basically, I have to rotate the Layer like a book flip. I have already done this without using the 30 degree transofrm, but I want it to look more 3D so applied the 30 degree transform along the x axis. So that it looks like the book is placed on a table.
And in order to rotate, setting the anchor point is necessary. If not, please advice otherwise...
instead of changing anchorPoint use
CATransform3DTranslate(transform, 50.0000f, 0.0000f, 0.0000f);
Translate along X by 50.00 points
Apply 0.40 percent of perspective or you can use the same code you are using right now
rotate the CAlayer using Y .
CATransform3D transform = CATransform3DIdentity;
CATransform3D tmp = CATransform3DIdentity;
transform = CATransform3DRotate(transform, 0.0146f, 0, 1, 0);
transform = CATransform3DTranslate(transform, 50.0000f, 0.0000f, 0.0000f);
tmp = CATransform3DIdentity;
tmp.m34 = 0.0040f;
transform = CATransform3DConcat(transform, tmp);
check the link for more reference.
let me know if it works.

Combining a UIView perspective transform with other CATranform3Ds

I'm writing an app such that sprites (subclasses of UIImageView) can be rotated, resized, and panned across the screen using gestures. I also would like to be able to apply a 3D perspective transformation to the sprites.
I have the rotate/resize/pan functionality working correctly, as well as the perspective transform. However, they don't seem to work together correctly. If I rotate an unmodified sprite, then try to skew it, the sprite 'resets' it's rotation, then applies the perspective. The opposite works though; if I skew first, I can apply any 2D transformation after without it resetting.
Here is the code I'm using: (rotate, resize, and pan are done using UIGestureRecognizers, whereas the skew uses a UISlider).
Rotate:
- (void)didRotateSprite:(UIRotationGestureRecognizer *)rotate
{
CGFloat angle = rotate.rotation;
CATransform3D transform = CATransform3DIdentity;
transform = CATransform3DRotate(spriteView.layer.transform, angle, 0, 0, 1);
spriteView.layer.transform = transform;
rotate.rotation = 0.0;
}
Resize:
- (void)didPinchSprite:(UIPinchGestureRecognizer *)pinch
{
CGFloat scale = pinch.scale;
CATransform3D transform = CATransform3DIdentity;
transform = CATransform3DScale(spriteView.layer.transform, scale, scale, 1);
view.layer.transform = transform;
pinch.scale = 1.0;
}
Perspective:
- (IBAction)perspectiveChanged:(UISlider *)slider
{
CATransform3D transform = CATransform3DIdentity;
transform.m34 = 1.0 / -100;
transform = CATransform3DRotate(transform, (1 - (slider.value * 2)) * M_PI_2, 1, 0, 0);
spriteView.layer.transform = transform;
}
Thank you!
Found the answer with a lot of debugging and the help of this question. The trick was to transform the view's perspective using:
spriteView.superview.layer.sublayerTransform = transform;
This recursively applies the transformation to the view's superview and any subviews contained in it. For more information about this, check out the documentation and Apple's Layer Style Properties guide too.

CGAffineTransformMakeRotation and CGAffineTransformMakeScale

How come only one of the above works in code?
Currently I am using the following...
image.transform = CGAffineTransformMakeRotation(M_PI/2.5);
image.transform = CGAffineTransformMakeScale(1.25, 1.25);
And my image is scaled to 125% like the second line says, however it is not rotate at all.
When I flip the code around to say...
image.transform = CGAffineTransformMakeScale(1.25, 1.25);
image.transform = CGAffineTransformMakeRotation(M_PI/2.5);
My image is rotated but not scaled...
Is there a way to use both of these in the same code?
I have these in my viewDidLoad method. Can anyone help me?
Thanks!
The second one should not use the Make rendition of the function. Thus you should, for example either:
CGAffineTransform transform = CGAffineTransformMakeScale(1.25, 1.25);
image.transform = CGAffineTransformRotate(transform, M_PI/2.5);
or
CGAffineTransform transform = CGAffineTransformMakeRotation(M_PI/2.5);
image.transform = CGAffineTransformScale(transform, 1.25, 1.25);
Contrast the Creating an Affine Transformation Matrix functions with the Modifying Affine Transformations functions.
CGAffineTransformMake are applied to the identity matrix, so you are rotating, but then is like you restore the identity and apply the scale. Use CGAffineTransformMake.. only for the first, for the second use CGAffineTransform...

What's the difference between setting the zPosition of a layer vs changing it via CATransform3DTranslate

I have a layer where I am modofying its m34 transform property to get perspective.
I would have expected that by changing the zPosition, the size will change (as it appears further away) however when I set the zPosition property, the size does not change, but it does when I use CATransform3DTranslate.
Why is this? What's the difference between the following:
CATransform3D transform = CATransform3DIdentity;
transform.m34 = 1.0 / -4000;
myLayer.transform = transform;
myLayer.zPosition = -500;
and
CATransform3D transform = CATransform3DIdentity;
transform.m34 = 1.0 / -4000;
transform = CATransform3DTranslate(transform, 0, 0, -500);
myLayer.transform = transform;
The latter works how I expect, but I want to understand why the first does not.
zPosition is just for the drawing order of siblings layers, not for perspective drawing: you can use it to get a "bring to front" / "send to back" effect without adding/removing the layer.

Resources