使用CGAffineTransform在视图上应用缩放和旋转。

14

我需要对一个视图进行缩放和旋转(使用手势实现),所以对于每个手势,我会更新当前的缩放和旋转值,类似下面这样:

self.scaleWidth *= gesture.scale; //When I detect an horizontal pinch
self.scaleHeight *= gesture.scale; //When I detect a vertical pinch
self.rotationAngle += gesture.rotationAngle; //When I detect a rotation

然后我执行以下操作来转换视图:

CGAffineTransform transform = CGAffineTransformScale(CGAffineTransformIdentity, self.scaleWidth, self.scaleHeight);
self.theSubViewToTransform.transform = CGAffineTransformRotate(transform, self.rotationAngle);

当我只进行缩放时,它工作得很好。当我先缩放再旋转时,旋转正常。但是在旋转后再次尝试缩放时,它就不太对了:缩放似乎是在旋转之后进行的,从而变形了我的图像结构。

我以为我已经做了应该做的事情来避免这种情况:每次从恒等变换开始,先进行缩放,然后旋转,但显然我错了...

有人知道我的实现有什么问题吗?

谢谢

4个回答

17

如果每次都从恒等变换开始,那么最终设置子视图的变换将仅包括当前手势的缩放和旋转。不要从恒等变换开始,而是从视图的当前变换开始。

CGAffineTransform transform = self.theSubViewToTransform.transform;
transform = CGAffineTransformScale(transform, self.scaleWidth, self.scaleHeight);
transform = CGAffineTransformRotate(transform, self.rotationAngle);
self.theSubViewToTransform.transform = transform;

这段代码第一次执行时,变换将从恒等变换开始。在后续的执行中,它将在旧的变换基础上进行新的更改。


这就是我一开始的做法,从上一个变换开始并每次添加边际变换,但这也没有帮助。如果您查看我的代码,您会发现我为每个变换更新参数,并使用边际更改使我的参数相对于全局视图初始化是绝对的,因此我应该从身份变换开始进行变换。 - Alexandre
我认为串联可能是问题所在。您正在使用的识别器是连续的,并且将发送多个回调。手势的比例和旋转因子来自手势的开始,而不是自上次回调以来的变化。您不应该每次手势更改时都乘以这些因素。但是,如果没有看到更多代码,很难做出更多判断。 - RPeck
好的,对不起,是我的错。我在最初的帖子中忘记提到我在每个回调函数中重置了识别器的值。 - Alexandre

7

对于 Swift 3

view.transform = CGAffineTransform(rotationAngle:  CGFloat.pi).concatenating(CGAffineTransform(scaleX: 0.4, y: 0.4))

3
你应该从当前的转换状态开始应用所需的转换。此外,你可以查看 CGAffineTransformConcat,它会在应用之前将其合并为单个变换。
CGAffineTransform transform = yourView.transform;
transform = CGAffineTransformConcat(CGAffineTransformScale(transform,  self.scaleWidth, self.scaleHeight),
                                    CGAffineTransformRotate(transform, self.rotationAngle));
yourView.transform = transform;

希望能帮到您!

2
尝试将变换应用于恒等变换,例如:
CGAffineTransform transform = CGAffineTransformIdentity;
transform = CGAffineTransformScale(transform, scaleWidth, scaleHeight);
transform = CGAffineTransformRotate(transform, angle);
viewToTransform.transform = transform;

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