這一節大家可以學到:
1. 前面一節的第一,第二點。
2. UIView 如何新增單擊和雙擊功能
3. 什麼是 Affine Transform
4. 通過 Affine Transform 來實現縮放動畫
什麼是 Affine Transformation?
影像的變形有很多種,一般來說 Affine Transformation 是2維變化,主要滿足以下兩點:
- 任意一個點 A,變形前後都屬於同一條線
- 每條線的中點變化後還是中點
在iOS 和 Mac OS 開發中,只要看到 Affine 就要記住這是跟 2 維圖形變形有關的,Affine Transform 是一個檢視在2維座標中的一個狀態。大家不用管什麼矩陣圓陣的,只要記住這樣定義的變數,它的預設值是 CGAffineTransformIdentity, 通過改變這個變數的值可以實現縮放,位移和旋轉(下一節介紹)。
Affine Transform 縮放
每個UIView 都有一個 transform 的屬性,它的預設值就是上面提到的。只要在動畫 block 中改變它的值就可以產生動畫效果。縮放有兩個常用的方法:
CGAffineTransformMakeScale(sx, sy)
CGAffineTransformScale(t, sx, xy)
sx: x 軸(長)縮放值
sy: y 軸(高)縮放值
t:CGAffineTransform 變數
在 Transform 方法中,包括以後的 3D Transform,只要方法名字裡有 ‘Make’ 就是基於預設值的改變,例如, 以下方法把 aView 基於預設狀態變長一倍,變高兩倍:
1 |
aView.transform = CGAffineTransformMakeScale(2, 3) |
如果把長度變成原來的一半,高度為原來的40%, 可以這樣:
1 |
aView.transform = CGAffineTransformMakeScale(0.5, 0.4) |
要注意,以下兩行程式碼執行後不會把檢視 x 和 y 各放大 4 倍,只會各放大 2 倍:
1 2 3 |
aView.transform = CGAffineTransformMakeScale(2, 2) aView.transform = CGAffineTransformMakeScale(2, 2) |
因為這是基於預設值放大2倍,不管執行多少次都只是預設值的2倍。
那麼現在問題來了,如果有一個UIButton, 每次按一下都比之前的x,y各放大1.5倍如何實現。這時候就得用到:CGAffineTransformScale(t, sx, xy)了
可以這樣實現:
1 2 3 4 5 6 7 |
@IBAction func buttonTapped (sender: AnyObject?) { aView.transform = CGAffineTransformScale(aView.transform, 1.5, 1.5) } |
這樣每次按button都會比原來放大 1.5×1.5 倍了。
示例程式碼
好了,基礎知識就這麼多,來看看程式碼吧,可以在這裡下載:
Swift: http://www.xmartcalc.com/ios-animation/codes/1.3/Animation1.3_Swift.zip
Objective-C: http://www.xmartcalc.com/ios-animation/codes/1.3/Animation1.3_OC.zip
這個程式開始後跟上一節的一樣,每當你單擊螢幕時,紫色的檢視就會放大;當你雙擊螢幕時,就會縮到原來的大小。
如果你對小牛哥做的APP感興趣,可以看看這裡:
小牛計算器 (打造最牛逼的計算神器:http://www.xmartcalc.com )
https://itunes.apple.com/gb/app/xmart-calculator+/id827740598?mt=8
智慧多翻譯 (3種語音同時翻譯)
https://itunes.apple.com/gb/app/multi-translate/id768642496?mt=8
程式碼正式開始:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 |
import UIKit class ViewController: UIViewController { //衡量,圓形檢視的大小 let kCircleViewSize:CGFloat = 90.0 //圓形檢視變數 var circleView: UIView! //動畫開始/停止標記 var animationHappening = false override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. //建立圓形檢視 setupCircleView() //建立點選事件 setupTapActions() } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } // 在這裡修改子檢視的位置 override func viewDidLayoutSubviews() { //避免圓形檢視被多次新增 //(只要從navigation controller 或者 modal view 返回,或者旋轉,這裡就會被呼叫), if(self.circleView.superview == nil) { //把圓形檢視新增到主檢視 self.view.addSubview(self.circleView) } //圓形檢視的位置在主檢視中間 self.circleView.center = self.view.center } // MARK: - Setup func setupCircleView() { //初始化子檢視 self.circleView = UIView(frame: CGRectMake(0,0,kCircleViewSize,kCircleViewSize)) //把檢視做成圓形 self.circleView.layer.cornerRadius = kCircleViewSize/2.0 //圓形檢視顏色 self.circleView.backgroundColor = UIColor.purpleColor() } func setupTapActions() { //新增單擊功能和響應方法 let singleTap = UITapGestureRecognizer(target: self, action: "tappedOnMainView:") singleTap.numberOfTapsRequired = 1 self.view.addGestureRecognizer(singleTap) //新增雙點選功能和響應方法 let doubleTap = UITapGestureRecognizer(target: self, action: "tappedOnMainView:") doubleTap.numberOfTapsRequired = 2 self.view.addGestureRecognizer(doubleTap) //雙擊時忽略單擊,這一行很重要! singleTap.requireGestureRecognizerToFail(doubleTap); } // MARK: - Actions func tappedOnMainView(tap: UITapGestureRecognizer) { //防止被一些傻逼在螢幕上亂點! //想看看後果是吧,把以下的 return 去掉 //執行後在螢幕上不停地點選就知道了 if(self.animationHappening) { return; } //預設狀態,為雙擊準備 var transform = CGAffineTransformIdentity //如果是單擊,x,y 就都放大 1.3 倍 if(tap.numberOfTapsRequired == 1) { transform = CGAffineTransformScale(self.circleView.transform, 1.3, 1.3) } //開始動畫 self.animationHappening = true UIView.animateWithDuration(0.3, animations: { () -> Void in //放大或者縮小 self.circleView.transform = transform }) { ( finished) -> Void in //動畫完成 self.animationHappening = false } } } |