将多个变换应用于UIView / CALayer

33

对于 UIView 和其相应的 CALayer 应用多个 transform 是否会有任何问题?

具体来说,是否可以 "混搭" CATransform3D 和 CGAffineTransform 而不会遇到问题?

同时,在动画另一个 transform 的变化时,直接设置某些 transforms 是否会出现问题?

是否有任何应该遵循的“规则”,或者任何设计模式可供使用?

4个回答

45

我意识到这并没有完全回答问题(或者远远不够),但如果你只使用CGAffineTransforms,你可以使用CGAffineTransformConcat()来组合多个变换。

只要正确地连接变换,即使其中一些是动画变换,另一些不是,这种方法也能正常工作。我不知道当你还进行图层变换时,这种方法是如何工作的。


2
CGAffineTransformConcat 对于两个变换效果很好,但对于三个或更多的变换有些棘手。请参见此答案以了解如何处理超过两个的变换。 - Suragch

37

pix0r是正确的,但这里还有一些关于此的更多信息。CGAffineTransformConcat()的官方文档

此外,这里有一个快速示例:

// Rotate 45 degrees
CGAffineTransform rotate = CGAffineTransformMakeRotation(45*(M_PI/180));
// Move to the left
CGAffineTransform translate = CGAffineTransformMakeTranslation(-50,0);
// Apply them to a view
self.view.transform = CGAffineTransformConcat(translate, rotate);

2
考虑到点是行向量,应该使用CGAffineTransformConcat(rotate,translate),对吗? - Plumenator
我也曾经这样想,但似乎需要先应用翻译。旋转是以翻译后的坐标系中心为轴心进行的,但如果先旋转再翻译,那么翻译就沿着旋转后的坐标系的轴进行。 - gamozzii
到了2022年,旋转然后平移对我有效。 - Pedro Paulo Amorim

12

Swift 3和4的语法略有改变。根据@whitehawk的答案进行调整:

// Rotate 45 degrees
var rotate = CGAffineTransform(rotationAngle: 45 * (.pi / 180))
// Move to the left
var translate = CGAffineTransform(translationX: -50, y: 0)
// Apply them to a view
self.view.transform = translate.concatenating(rotate)

-1
我成功地同时旋转和平移了一个imageView,方式如下:
float scaleFactor_x   = 2.8;
float scaleFactor_y   = 2.45;
imgBigBallBasic.frame = CGRectMake(112, 20, 100, 100);
CGAffineTransform scaleTrans  = CGAffineTransformMakeScale(scaleFactor_x, scaleFactor_y);
CGAffineTransform translateTrans  = CGAffineTransformMakeTranslation(0, 55);
imgBigBallBasic.contentMode = UIViewContentModeScaleAspectFit;
imgBigBallBasic.transform = CGAffineTransformConcat(translateTrans, scaleTrans);
imgBigBallBasic.frame = CGRectMake(112, 20, 100, 100);
imgBigBallBasic.center = [[imgBigBallBasic window] center];
[UIView commitAnimations];

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接