Как применить несколько преобразований в Swift

Я хотел бы применить несколько преобразований к UIView (или подкласс UIView), такие как перевод, вращение и масштабирование. Я знаю, что два преобразования могут быть применены с CGAffineTransformConcat, но как мне это сделать, если у меня есть три или более преобразований?

Я видел эти вопросы:

но эти вопросы задают нечто иное, и данные ответы просто говорят о применении двух преобразований с CGAffineTransformConcat, Кроме того, они используют Objective-C, а не Swift.

3 ответа

Решение

Вы можете применить несколько преобразований, накладывая их друг на друга.

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)

Эта серия преобразований создает изображение справа:

Спасибо за этот ответ за то, что научил меня, как это сделать.

Заметки

  • Порядок, в котором вы применяете преобразования, имеет значение. Например, если преобразования были выполнены в обратном порядке, это привело бы к следующему результату.

    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)НЕ меняется. он просто возвращает новый CGAffineTransformчто вам нужно НАЗНАЧИТЬ обратно view.transform.

      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)
Другие вопросы по тегам