CATransform3D not working properly - iphone

CATransform3D not working properly, I am using the below code. My problem is If I change the transform Its working fine. Once I release my finger and then make more transform the image goes to the Initial image. How to set the last transform? I am using PanGesture for the transform. Please give some Idea. Thanks in advance.
if ([recognizer respondsToSelector:#selector(translationInView:)]) {
CGPoint translation = [(UIPanGestureRecognizer *)recognizer translationInView:recognizer.view.superview];
CALayer *layer = self.layer;
CATransform3D rotationAndPerspectiveTransform = CATransform3DIdentity;
rotationAndPerspectiveTransform.m34 = 1.0 / -500;
rotationAndPerspectiveTransform = CATransform3DRotate(rotationAndPerspectiveTransform, translation.x * M_PI / 180.0f, 0.0f, 1.0f, 0.0f);
layer.transform = rotationAndPerspectiveTransform;
rotationAndPerspectiveTransform.m34 = 1.0 / -500;
rotationAndPerspectiveTransform = CATransform3DRotate(rotationAndPerspectiveTransform, -translation.y * M_PI / 180.0f, 1.0f, 0.0f, 0.0f);
layer.transform = rotationAndPerspectiveTransform;
}

CATransform3DIdentity means you resetting the transformation every time your view receives touch. Use CATransform3D rotationAndPerspectiveTransform = layer.transform; instead.

Related

How to make image rotation and 3D transform simultaneously?

I am working on image editing application(resize, rotation, 3d transform). If I am rotate the image and then make 3D transform. Its going to initial image. Otherwise I am change the 3D transform then make rotation, Its also goes to the initial state.
For image 3D Transform I am using below code :
- (void)moveImage:(UIPanGestureRecognizer *)recognizer
{
if ([recognizer respondsToSelector:#selector(translationInView:)]) {
CGPoint translation = [(UIPanGestureRecognizer *)recognizer translationInView:recognizer.view.superview];
CALayer *layer = self.layer;
CATransform3D rotationAndPerspectiveTransform = CATransform3DIdentity;
rotationAndPerspectiveTransform.m34 = 1.0 / 500.0;
rotationAndPerspectiveTransform = CATransform3DRotate(rotationAndPerspectiveTransform, - self.xTranslation / 50.0 * M_PI / 180.0f, 0.0f, 1.0f, 0.0f);
layer.transform = rotationAndPerspectiveTransform;
rotationAndPerspectiveTransform.m34 = - 1.0 / 500.0;
rotationAndPerspectiveTransform = CATransform3DRotate(rotationAndPerspectiveTransform, - self.yTranslation / 50.0 * M_PI / 180.0f, 1.0f, 0.0f, 0.0f);
layer.transform = rotationAndPerspectiveTransform;
}
}
For image Rotation I am using below code :
- (void)rotateImage:(UIRotationGestureRecognizer *)recognizer
{
if (state == RSImageViewStateResizing) {
recognizer.view.transform = CGAffineTransformRotate(recognizer.view.transform, recognizer.rotation);
recognizer.rotation = 0;
}
}
How to I fix this issue. Always welcome your suggestions, sample code, Sample project, any App store applications. Thanks in advance. Any one help me.
Use CAAnimationGroup to combine multiple animation into one
CAAnimationGroup *theGroup = [CAAnimationGroup animation];
theGroup.animations=[NSArray arrayWithObject:resizeAnimation, rotationAnimation, 3d transformAnimation];// add here your CAAnimation reference and CATransform3D reference
[layer addAnimation:theGroup forKey:#"animatePosition"];

don't want to rotate the image in carousel while rotating carousel

I am using Nick Lockwood carousel and type is Wheel Carousel. I am using the images as items in carousel. The problem is when I rotate the carousel the image also rotates, i.e. consider a person image, then the person image gets tilted, which I don't want, i.e. I don't want to rotate that particular image while rotating whole carousel. Can anyone please help?
Look in the implementation of - (CATransform3D)transformForItemView:(UIView *)view withOffset:(CGFloat)offset; Find the case iCarouselTypeWheel: and case iCarouselTypeInvertedWheel: block.
Change the code that generates the final transforms (for both the vertical and horizontal cases) to reverse the applied rotation:
transform = CATransform3DTranslate(transform, 0.0f, radius, 0.0f);
transform = CATransform3DRotate(transform, angle * offset, 0.0f, 0.0f, 1.0f);
// this is the transform the existing code returns...
transform = CATransform3DTranslate(transform, 0.0f, -radius, offset * 0.01f);
// instead you reverse the rotation before returning...
return CATransform3DRotate(transform, -(angle * offset), 0.0f, 0.0f, 1.0f);
I hope that helps.
Have a look at the file iCarousel.m, and find the - (CATransform3D)transformForItemView:(UIView *)view withOffset:(CGFloat)offset method; inside of it you will find this block:
case iCarouselTypeWheel:
case iCarouselTypeInvertedWheel:
{
NSInteger count = [self valueForTransformOption:iCarouselTranformOptionCount withDefault:
MIN(numberOfVisibleItems, numberOfItems + numberOfPlaceholdersToShow)];
CGFloat arc = [self valueForTransformOption:iCarouselTranformOptionArc withDefault:M_PI * 2.0f];
CGFloat radius = [self valueForTransformOption:iCarouselTranformOptionRadius withDefault:itemWidth * (CGFloat)count / arc];
CGFloat angle = [self valueForTransformOption:iCarouselTranformOptionAngle withDefault:arc / (CGFloat)count];
if (type == iCarouselTypeInvertedWheel)
{
radius = -radius;
angle = -angle;
}
if (vertical)
{
transform = CATransform3DTranslate(transform, -radius, 0.0f, 0.0f);
/* this */ transform = CATransform3DRotate(transform, angle * offset, 0.0f, 0.0f, 1.0f);
return CATransform3DTranslate(transform, radius, 0.0f, offset * 0.01f);
}
else
{
transform = CATransform3DTranslate(transform, 0.0f, radius, 0.0f);
/* this */ transform = CATransform3DRotate(transform, angle * offset, 0.0f, 0.0f, 1.0f);
return CATransform3DTranslate(transform, 0.0f, -radius, offset * 0.01f);
}
}
Try simply to comment out the two lines:
transform = CATransform3DRotate(transform, angle * offset, 0.0f, 0.0f, 1.0f);
and see what happens; I guess that the face will not be rotated, but then you might need to adjust the translation...
Try conditionally rotating the image depending on the device orientation in the
- (UIView *)carousel:(iCarousel *)carousel viewForItemAtIndex:(NSUInteger)index reusingView:(UIView *)view;
delegate method.
Using the code from the above answers I wasn't able to really fix the issue. I reused part of the comments but not the code. What worked for me was this.
if (_vertical)
{
transform = CATransform3DTranslate(transform, -radius, 0.0, 0.0);
transform = CATransform3DRotate(transform, angle * offset, 0.0, 0.0, 1.0);
transform = CATransform3DTranslate(transform, radius, 0.0, offset * 0.01);
return CATransform3DRotate(transform, -(angle * offset), 0.0, 0.0, 1.0);
}
else
{
transform = CATransform3DTranslate(transform, 0.0, radius, 0.0);
transform = CATransform3DRotate(transform, angle * offset, 0.0, 0.0, 1.0);
transform = CATransform3DTranslate(transform, 0.0, -radius, offset * 0.01);
return CATransform3DRotate(transform, -(angle * offset), 0.0, 0.0, 1.0);
}

CATransForm3D matrix issue

If you want to rotate an object using core animation, in radians, in the z axis, which of the following key paths of layer's CATransform3D matrix will you use? (more than 1 options can be right).
rotation
rotation.xy
rotation.x
rotation.y
rotation.z
Not totally clear about the options you gave, but I use the code below to do rotation:
[[_yourView layer] setAnchorPoint:CGPointMake(0.0f, 0.5)];
[UIView animateWithDuration:1.0f
delay:0.0f
options:UIViewAnimationCurveEaseInOut
animations:^{
CATransform3D rotation = CATransform3DIdentity;
rotation.m34 = 1.0f / -300.0f;
rotation = CATransform3DRotate(rotation, -60.0f * M_PI / 180.0f, 0.0f, 1.0f, 0.0f);
[[_yourView layer] setTransform:rotation];
}
completion:nil];
It is rotated in y axis(so, the view will change in z direction), you can set the rotation for other axis by setting the params below:
rotation = CATransform3DRotate(rotation, -60.0f * M_PI / 180.0f, 0.0f, 1.0f, 0.0f);
None of the above. Use transform.rotation.z

How to rotate an UIImageView with CATransform3DRotate make an effect like Door Opening?

I've read and try this article (Opening door effect using Core Animation)
And I implement following code in my app:
CALayer *layer = threeHomeView.layer;
CATransform3D initialTransform = threeHomeView.layer.transform;
initialTransform.m34 = 1.0 / -900;
[UIView beginAnimations:#"Scale" context:nil];
[UIView setAnimationDuration:3];
layer.transform = initialTransform;
CATransform3D rotationAndPerspectiveTransform = threeHomeView.layer.transform;
rotationAndPerspectiveTransform = CATransform3DRotate(rotationAndPerspectiveTransform
, 40.0f * M_PI / 180.0f
, 0.0f
, 1.0f
, 0.0f);
layer.transform = rotationAndPerspectiveTransform;
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:#selector(threeHomeFlyOut)];
[UIView commitAnimations];
threeHomeView is an UIImageView.
MY QUESTION IS: the image can only rotate by middle vertical line of the image, but I want it to rotate by left vertical line of the image.
Use CATransform3DRotate like you did in combination with CATransform3DTranslate to rotate around the edge, like I did in this answer. Here's a little excerpt (you will need to modify this for your own uses):
CATransform3D t = CATransform3DIdentity;
t = CATransform3DTranslate(t, 0, -self.view.bounds.size.height/2, 0);
t = CATransform3DRotate(t, rec.scale * M_PI, 1, 0, 0);
t = CATransform3DTranslate(t, 0, -self.view.bounds.size.height/2, 0);
self.view.layer.transform = t;
- (void)awakeFromNib {
transformed = [CALayer layer];
transformed.frame = self.bounds;
[self.layer addSublayer:transformed];
CALayer *imageLayer = [CALayer layer];
imageLayer.frame = CGRectMake(10.0f, 4.0f, 300.0f, 226.0f);
imageLayer.transform = CATransform3DMakeRotation(20.0f * M_PI / 180.0f,
1.0f, 0.0f, 0.0f);
imageLayer.contents = (id)[[UIImage imageNamed:#"IMG_0051.png"] CGImage];
[transformed addSublayer:imageLayer];
imageLayer = [CALayer layer];
imageLayer.frame = CGRectMake(10.0f, 234.0f, 300.0f, 226.0f);
imageLayer.transform = CATransform3DMakeRotation(-20.0f * M_PI / 180.0f,
1.0f, 0.0f, 0.0f);
imageLayer.contents = (id)[[UIImage imageNamed:#"IMG_0089.png"] CGImage];
[transformed addSublayer:imageLayer];
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
previousLocation = [[touches anyObject] locationInView:self];
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
CGPoint location = [[touches anyObject] locationInView:self];
// BJL: The following is the code I used in Molecules to do 3-D rotation
CATransform3D currentTransform = transformed.sublayerTransform;
CGFloat displacementInX = location.x - previousLocation.x;
CGFloat displacementInY = previousLocation.y - location.y;
CGFloat totalRotation = sqrt(displacementInX * displacementInX + displacementInY * displacementInY);
CATransform3D rotationalTransform = CATransform3DRotate(currentTransform, totalRotation * M_PI / 180.0,
((displacementInX/totalRotation) * currentTransform.m12 + (displacementInY/totalRotation) * currentTransform.m11),
((displacementInX/totalRotation) * currentTransform.m22 + (displacementInY/totalRotation) * currentTransform.m21),
((displacementInX/totalRotation) * currentTransform.m32 + (displacementInY/totalRotation) * currentTransform.m31));
previousLocation = location;
transformed.sublayerTransform = rotationalTransform;
}

CATransform3D rotate causes half of image to disappear

I'm using the following code to rotate an image, but half the image (down the y-axis) that has been rotated "out of" the page, disappears. How to fix? heading is in radians.
CALayer *layer = myUIImageView.layer;
CATransform3D rotationAndPerspectiveTransform = CATransform3DIdentity;
rotationAndPerspectiveTransform.m34 = 1.0 / 500;
rotationAndPerspectiveTransform = CATransform3DRotate(rotationAndPerspectiveTransform, heading, 0.0f, 1.0f, 0.0f);
layer.transform = rotationAndPerspectiveTransform;
The solution to this was to set the zPosition property of all my layers appropriately. Thanks is due to #Brad Larson, who suggested this solution in a comment here. It seems that, when you start using CATransform3D, the normal zindex view hierarchy established by addsubview is thrown out the window.
layer.anchorPoint = CGPointMake(0.0, 0.0);
Setting the anchorPoint to {0.0, 0.0} works as well (as Liam already pointed out).
Here's the full code snippet for changing the anchorPoint without changing the layer's position on screen:
layer.anchorPoint = CGPointMake( 0.0, 0.0 );
CGPoint position = layer.position;
CGSize size = layer.bounds.size;
CGFloat posX = position.x - size.width / 2.0;
CGFloat posY = position.y - size.height / 2.0;
layer.position = CGPointMake( posX, posY );