从CATransform3D到CGAffineTransform [英] From CATransform3D to CGAffineTransform
问题描述
我正在使用以下功能将脉冲效果应用于视图
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"];
}
我想使用以下方法获得相同的结果
推荐答案
这可能吗?将 CATransform3D
转换为 CGAffineTransform
,但是您将失去一些功能。我发现将图层及其祖先的聚合变换转换为 CGAffineTransform
很有用,因此可以使用Core Graphics进行渲染。约束是:
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:
- 您的输入将在XY平面上视为平坦
- 您的输出也会在XY平面上视为平坦的。
- 从
.m34
的透视/透视将被抵消
- Your input will be treated as flat in the XY plane
- Your output will be treated as flat in the XY plane too
- Perspective / foreshortening from
.m34
will be neutralized
如果这对您有帮助:
// 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);
您首先要在3D变换中完成所有工作,例如从上层连接起来,然后然后将汇总的 CATransform3D
转换为 CGAffineTransform
。鉴于图层开始是平坦的并渲染到平坦的目标上,所以我发现这非常合适,因为我的3D旋转变成了2D剪切。我还发现牺牲透视图是可以接受的。之所以无法解决,是因为仿射变换必须保留平行线。
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.
例如,要使用Core Graphics渲染3D变换的图层,您可以将变换连接起来(尊重锚点!),然后转换为仿射,最后:
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);
这篇关于从CATransform3D到CGAffineTransform的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!