Как применить несколько преобразований в Swift
Я хотел бы применить несколько преобразований к UIView
(или подкласс UIView
), такие как перевод, вращение и масштабирование. Я знаю, что два преобразования могут быть применены с CGAffineTransformConcat
, но как мне это сделать, если у меня есть три или более преобразований?
Я видел эти вопросы:
- Применение нескольких преобразований к UIView / CALayer
- Использование нескольких CGAffineTransforms в текстовой матрице
но эти вопросы задают нечто иное, и данные ответы просто говорят о применении двух преобразований с 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)
Смотрите также
- CGAffineTransform Reference (документы)
- Преобразования (документы)
- Swift: перевод и поворот CGContext, визуальное объяснение (iOS/Xcode)
- Демистификация CGAffineTransform
Этот ответ был протестирован с 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)