如何在 Swift 中应用多个转换

How to apply multiple transforms in Swift

我想对 UIView(或 UIView 的子类)应用多个变换,例如平移、旋转和缩放。我知道 CGAffineTransformConcat 可以应用两个变换,但如果我有三个或更多变换,我该怎么做?

我看到了这些问题:

但是这些问题问的是不同的东西,给定的答案只是谈论用 CGAffineTransformConcat 应用两个转换。此外,他们使用 Objective-C 而不是 Swift。

您可以通过将它们堆叠在一起来应用多个变换。

var t = CGAffineTransform.identity
t = t.translatedBy(x: 100, y: 300)
t = t.rotated(by: CGFloat.pi / 4)
t = t.scaledBy(x: -1, y: 2)
// ... add as many as you want, then apply it to to the view
imageView.transform = t

或更简洁(但不一定具有可读性):

imageView.transform = CGAffineTransform.identity.translatedBy(x: 100, y: 300).rotated(by: CGFloat.pi / 4).scaledBy(x: -1, y: 2)

这一系列的变换产生了右边的图像:

感谢 this answer 教我怎么做。

备注

  • 应用转换的顺序很重要。例如,如果以相反的顺序进行转换,则会产生以下结果。

    t = t.scaledBy(x: -1, y: 2)
    t = t.rotated(by: CGFloat.pi / 4)
    t = t.translatedBy(x: 100, y: 300)
    

另见

此答案已通过 Swift 4

测试

在 Swift 3 中,这些已被 CGAffineTransform 本身的函数所取代,可以链接。

extension CGAffineTransform {
    public func translatedBy(x tx: CGFloat, y ty: CGFloat) -> CGAffineTransform
    public func scaledBy(x sx: CGFloat, y sy: CGFloat) -> CGAffineTransform
    public func rotated(by angle: CGFloat) -> CGAffineTransform
}

例如

let transform = CGAffineTransform(scaleX: 1.0, y: 3.0).translatedBy(x: 12, y: 9).rotated(by: 17.0)

诀窍在于 view.transform.translatedBy(x: 100, y: 100) 没有改变 view.transform。它只是 returns 您需要分配回 view.transform 的新 CGAffineTransform

view.transform = view.transform.translatedBy(x: 100, y: 100)

您可以根据需要多次或按顺序执行此操作

view.transform = view.transform.translatedBy(x: 100, y: 100).rotated(by: CGFloat.pi / 2).scaledBy(x: 2, y: 2)