Reputation: 511706
I would like to apply multiple transforms to a UIView
(or subclass of UIView
), such as translate, rotate, and scale. I know that two transforms can be applied with CGAffineTransformConcat
, but how do I do it if I have three or more transforms?
I have seen these questions:
but these questions are asking something different, and the given answers just talk about applying two transforms with CGAffineTransformConcat
. Also, they use Objective-C rather than Swift.
Upvotes: 69
Views: 44184
Reputation: 980
the trick is that
view.transform.translatedBy(x: 100, y: 100)
is NOT changing view.transform
. it just returns the new CGAffineTransform
that you need to ASIGN back to view.transform
.
view.transform = view.transform.translatedBy(x: 100, y: 100)
You can do that as many times as you need or in a sequence
view.transform = view.transform.translatedBy(x: 100, y: 100).rotated(by: CGFloat.pi / 2).scaledBy(x: 2, y: 2)
Upvotes: 0
Reputation: 511706
You can apply multiple transforms by stacking them on top of each other.
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
Or more compactly (but not necessarily as readable):
imageView.transform = CGAffineTransform.identity.translatedBy(x: 100, y: 300).rotated(by: CGFloat.pi / 4).scaledBy(x: -1, y: 2)
This series of transforms produces the image on the right:
Thanks to this answer for teaching me how to do it.
The order in which you apply the transforms matters. For example, if the transforms were done in the opposite order it would produce the following result.
t = t.scaledBy(x: -1, y: 2)
t = t.rotated(by: CGFloat.pi / 4)
t = t.translatedBy(x: 100, y: 300)
This answer has been tested with Swift 4
Upvotes: 160
Reputation: 1953
In Swift 3, these have been replaced by functions on CGAffineTransform itself, which can be chained.
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
}
so for example
let transform = CGAffineTransform(scaleX: 1.0, y: 3.0).translatedBy(x: 12, y: 9).rotated(by: 17.0)
Upvotes: 33