I'm using the following function to apply a pulse effect to a view
- (void)pulse {
CATransform3D trasform = CATransform3DScale(self.layer.transform, 1.15, 1.15, 1);
trasform = CATransform3DRotate(trasform, angle, 0, 0, 0);
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform"];
animation.toValue = [NSValue valueWithCATransform3D:trasform];
animation.autoreverses = YES;
animation.duration = 0.3;
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
animation.repeatCount = 2;
[self.layer addAnimation:animation forKey:@"pulseAnimation"];
}
I would like to obtain the same result using the CGAffineTransform self.transform instead of the CATransform3D self.layer.transform. Is this possible?
It's possible convert a CATransform3D
to a CGAffineTransform
, but you will lose some capabilities. I found it useful to convert the aggregate transform of a layer and its ancestors into a CGAffineTransform
so I could render it with Core Graphics. The constraints are:
.m34
will be neutralizedIf that sounds OK for your purposes:
// m13, m23, m33, m43 are not important since the destination is a flat XY plane.
// m31, m32 are not important since they would multiply with z = 0.
// m34 is zeroed here, so that neutralizes foreshortening. We can't avoid that.
// m44 is implicitly 1 as CGAffineTransform's m33.
CATransform3D fullTransform = <your 3D transform>
CGAffineTransform affine = CGAffineTransformMake(fullTransform.m11, fullTransform.m12, fullTransform.m21, fullTransform.m22, fullTransform.m41, fullTransform.m42);
You will want to do all your work in 3D transforms first, say by concatenating from your superlayers, and then finally convert the aggregate CATransform3D
to a CGAffineTransform
. Given that layers are flat to begin with and render onto a flat target, I found this very suitable since my 3D rotations became 2D shears. I also found it acceptable to sacrifice foreshortening. There's no way around that because affine transforms have to preserve parallel lines.
To render a 3D-transformed layer using Core Graphics, for instance, you might concatenate the transforms (respecting anchor points!), then convert to affine, and finally:
CGContextSaveGState(context);
CGContextConcatCTM(context, affine);
[layer renderInContext:context];
CGContextRestoreGState(context);
Of course. If you do a search on CGAffineTransform in the Xcode docs, you'll find a chapter titled "CGAffineTransform Reference". In that chapter is a section called "Functions". It includes functions that are equivalent to CATransform3DScale (CGAffineTransformScale ) and CATransform3DRotate (CGAffineTransformRotate).
Note that your call to CATransform3DRotate doesn't really make sense. You need to rotate around an axis, and you're passing 0 for all 3 axes. Typcially you want to use CATransform3DRotate(trasform, angle, 0, 0, 1.0) to rotate around the Z axis. To quote the docs:
If the vector has zero length the behavior is undefined.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With