这一节大家可以学到:
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: { |