利用 CGAffineTransform 縮放,位移,旋轉和鏡像翻轉
利用 CGAffineTransform 我們可以像魔法師般對 view 下魔法,控制 view 的 transform property,要它聽話地縮放,位移和旋轉。(transform 的中文是轉換的意思)
接下來就讓我們好好來認識它,施展魔法讓彼得潘縮放,位移和旋轉吧。
override func viewDidLoad() {
super.viewDidLoad()
let imageView = UIImageView(image: UIImage(named: "peter"))
view.addSubview(imageView)
}
搭配 scale 縮放
利用 CGAffineTransform 的 init(scaleX:y:) 產生縮放的 CGAffineTransform,參數 scaleX & y 分別傳入縮放的比例,因此以下程式將讓圖片的寬高變成原來的兩倍。
imageView.transform = CGAffineTransform(scaleX: 2, y: 2)
我們也可以先用 CGAffineTransform.identity 產生沒有套用任何效果的 CGAffineTransform,然後再呼叫 function scaledBy(x:y:),產生縮放的效果。
imageView.transform = CGAffineTransform.identity.scaledBy(x: 2, y: 2)
鏡像翻轉(mirror)
當我們利用 scale 參數縮放大小時,傳入負數還可以實現有趣的鏡像翻轉效果。比方以下例子的 scaleX 傳入 -1 時,圖片將維持原本的寬度,但變成鏡像左右翻轉。
let imageView = UIImageView(image: UIImage(named: "peter"))
view.addSubview(imageView)
let mirrorImageView = UIImageView(image: UIImage(named: "peter"))
mirrorImageView.frame.origin.x = imageView.frame.maxX + 10
mirrorImageView.transform = CGAffineTransform(scaleX: -1, y: 1)
view.addSubview(mirrorImageView)
若是將 scale 的 y 設為 -1,則會變成圖片維持原本的高度,但變成鏡像上下翻轉。
mirrorImageView.transform = CGAffineTransform(scaleX: 1, y: -1)
搭配 translation 位移
利用 CGAffineTransform 的 init(translationX:y:) 產生位移的 CGAffineTransform,參數 translationX & y 分別傳入水平和垂直移動的距離,因此以下程式將讓圖片向右移動 100,向下移動 300 points。
imageView.transform = CGAffineTransform(translationX: 100, y: 300)
我們也可以先用 CGAffineTransform.identity 產生沒有套用任何效果的 CGAffineTransform,然後再呼叫 function translatedBy(x:y:),產生位移的效果。
imageView.transform = CGAffineTransform.identity.translatedBy(x: 100, y: 300)
搭配 rotationAngle 旋轉
利用 CGAffineTransform 的 init(rotationAngle:) 產生旋轉的 CGAffineTransform,參數 rotationAngle 傳入旋轉的弧度。
角度 1 度對應弧度 π / 180。因此以下程式將讓彼得潘旋轉 45 度,展現最帥氣的角度。
let oneDegree = CGFloat.pi / 180
imageView.transform = CGAffineTransform(rotationAngle: oneDegree * 45)
我們也可以先用 CGAffineTransform.identity 產生沒有套用任何效果的 CGAffineTransform,然後再呼叫 function rotated(by:),產生 旋轉的效果。
let oneDegree = CGFloat.pi / 180
imageView.transform = CGAffineTransform.identity.rotated(by: oneDegree * 45)
結合縮放,位移和旋轉
結合縮放,位移和旋轉時,順序很重要,因為背後牽扯到矩陣的數學運算,所以先位移再縮放跟先縮放再位移是不一樣的。
- 方法 1
let oneDegree = CGFloat.pi / 180
imageView.transform = CGAffineTransform.identity.translatedBy(x: 100, y: 300).scaledBy(x: 0.5, y: 0.5).rotated(by: oneDegree * 45)
- 方法 2
使用 concatenating 串接 transform。一樣要特別注意順序問題,以下程式的結果跟方法 1 一樣,不過是用 rotateTransform concatenating scaleTransform,然後再 concatenating translateTransform。
let oneDegree = CGFloat.pi / 180
let translateTransform = CGAffineTransform(translationX: 100, y: 300)
let scaleTransform = CGAffineTransform(scaleX: 0.5, y: 0.5)
let rotateTransform = CGAffineTransform(rotationAngle: oneDegree * 45)
imageView.transform = rotateTransform.concatenating(scaleTransform).concatenating(translateTransform)
沒有任何效果的 CGAffineTransform
讓圖片呈現原本的模樣。
imageView.transform = CGAffineTransform.identity
練習
定義 function 運用 UIBezierPath 繪製可愛圖案,然後在 viewDidLoad 裡呼叫 function 多次,調整圖案的縮放,位移和旋轉。
範例:
參考以下連結 Ting 同學繪製的 Apple,將她的程式寫在 function addAppleView 裡。
func addAppleView(moveX: CGFloat, moveY: CGFloat, rotateDegree: CGFloat, scale: CGFloat) {
// 此處請貼上 Ting 同學繪製 Apple 的程式
let oneDegree = CGFloat.pi / 180
flagBackground.transform = CGAffineTransform.identity.translatedBy(x: moveX, y: moveY).scaledBy(x: scale, y: scale).rotated(by: oneDegree * rotateDegree)
view.addSubview(flagBackground)
}
在 viewDidLoad 裡呼叫 function addAppleView。
override func viewDidLoad() {
super.viewDidLoad()
addAppleView(moveX: -30, moveY: -80, rotateDegree: 45, scale: 2)
addAppleView(moveX: 0, moveY: 20, rotateDegree: 70, scale: 0.75)
addAppleView(moveX: 30, moveY: 100, rotateDegree: 90, scale: 0.5)
}