OC语言中,动画创建有两种方法
1)头尾式动画,非常少用,了解即可。例如:
/*动画的第一种实现方法:头尾式动画*/
// 开始动画
[UIView beginAnimations:nil context:nil];
// 设置动画时间
[UIView setAnimationDuration:2];
// ------------------动画代码---------------
self.imageView.transform = CGAffineTransformTranslate(self.imageView.transform, 10, 100);
// 提交动画
[UIView commitAnimations];
2)Block动画。最常用,必须掌握相关参数含义。例如
/*Block动画*/
/*
第一个参数:动画执行时间
第二个参数:动画延迟执行时间
第三个参数:弹簧阻尼系数 取值范围 0 - 1 ; 0:没有阻力 1:阻力最大,没有弹簧效果
第四个参数:初速度
第五个参数:动画效果
第六个参数:动画的block代码
第七个参数:动画执行完成后执行的block
*/
[UIView animateWithDuration:3 //表示整个动画时间3s
delay:0 //表示没有延迟
usingSpringWithDamping:1 //表示阻力最大,无弹簧效果
initialSpringVelocity:1 //表示初速度为1
options:UIViewAnimationOptionCurveLinear //线性
animations:^{
self.imageView.transform = CGAffineTransformTranslate(self.imageView.transform, 10, 100);//动画
}
completion:^(BOOL finished) {
NSLog(@"飘过去了。。。”); //动画执行完毕后执行的语句
}];
有一些循环动画。例如如下代码(支付宝咻一咻功能部分代码)
for (int i = 0; i < 6; i++) {
// 创建光环视图
UIView *circleView = [self createCircleView];
// 动画放大:
[UIView animateWithDuration:3 delay:0.5 * i options:UIViewAnimationOptionCurveLinear animations:^{
//动画代码
//[UIView setAnimationRepeatCount:MAXFLOAT];//这一句可以无限循环
circleView.transform = CGAffineTransformMakeScale(10, 10);
//透明度。一个属性是否能放在动画代码中,可参阅UIView中对属性是否标注animatable。
circleView.alpha = 0;
} completion:^(BOOL finished) {
[circleView removeFromSuperview];//动画执行完毕后,要删除创建的视图
}];
动画中经常用到UIView的一个很重要属性:transform。
@property(nonatomic) CGAffineTransform transform;
仿射变换常用的方法有:
//创建一个仿射变换
//Returns an affine transformation matrix constructed from values you provide.
CGAffineTransform CGAffineTransformMake ( CGFloat a, CGFloat b, CGFloat c, CGFloat d, CGFloat tx, CGFloat ty );
//旋转变换 angle为弧度
//Returns an affine transformation matrix constructed from a rotation value you provide.
CGAffineTransformMakeRotation(<#CGFloat angle#>)
//Returns an affine transformation matrix constructed by rotating an existing affine transform.
CGAffineTransformRotate(<#CGAffineTransform t#>, <#CGFloat angle#>)
//缩放变换 sx、sy为缩放比率
//Returns an affine transformation matrix constructed from scaling values you provide.
CGAffineTransformMakeScale(<#CGFloat sx#>, <#CGFloat sy#>)
//Returns an affine transformation matrix constructed by scaling an existing affine transform.
CGAffineTransformScale(<#CGAffineTransform t#>, <#CGFloat sx#>, <#CGFloat sy#>)
//平移变换,tx、ty分别为水平 和 垂直 偏移量
//Returns an affine transformation matrix constructed from translation values you provide.
CGAffineTransformMakeTranslation(<#CGFloat tx#>, <#CGFloat ty#>)
//Returns an affine transformation matrix constructed by translating an existing affine transform.
CGAffineTransformTranslate(<#CGAffineTransform t#>, <#CGFloat tx#>, <#CGFloat ty#>)
//单位矩阵,常量,用于还原transform
CGAffineTransformIdentity
相关知识点:
1、图像变换中注意frame与bounds的区别
1)frame 与 bounds 都是UIView中的CGRect 属性,都有(origin,size)组成
2)修改frame.size,UIView是以左上角为中心点变化。(UIView的frame.orign没有变化,UIView的bounds属性是否发生变化??)
修改bounds,size,UIView是以UIView的center为中心点变化的。(UIView的frame.orign发生变化,frame.size无变化,bounds.size变化,bounds.orign有变化)
//结论
//修改frame.size,图像改变
// frame.orign不变。frame.size变化是以UIView的frame.orign为轴变动,因此frame.orign不动,在superView坐标系中的位置也没变
// frame.size改变
// bounds.orign不变,自身坐标系始终不变
// bounds.size改变,因为bounds.size与frame.size是相互影响的,修改一个,另一个会发生改变
//结论:
//修改bounds.size,图像改变
// bounds.orign不变,自身坐标系始终不变
// bounds.size改变
// frame.orign改变,因为bounds.size改变是以UIView中心点为轴变动的,故frame.orign在suerView中的相对位置改变
// frame.size改变,因为bounds.size与frame.size是相互影响的,修改一个,另一个会发生改变
//结论:
//修改frame.orign,图像移动位置
// frame.orign改变
// frame.size不变
// bounds.orign不变,自身坐标系始终不变
// bounds.size不变
//结论:
//修改bounds.orign, 图像位置不变
// frame.orign不变,因为superView参考坐标系没变
// frame.size不变
// bounds.orign改变,自身坐标系始终改变
// bounds.size不变
tips:使用NSStringFromCGRect打印矩阵。
2、属性与成员变量的区别
成员变量使用的是以下定义方法:
@interface ViewController ()
{
NSString *_name;
}
@end
而属性,则是用@property定义的。
用@property定义属性,为类自动生成了一个下划线的成员变量,同时为成员变量自动生成了setter/getter方法。
不需要使用getter、setter方法访问类数据的时候,可以用成员变量。
属性使用的更加广泛。
3、分类中的属性
分类是对类的拓展,一般只能定义方法。但是也可以定义属性,但是不能为属性生成getter、setter方法
需要手动完成getter、setter方法。例如:
@interface NSObject (Extention)
@property (nonatomic, copy) NSString *name;
@end
@implementation NSObject (Extention)
// 只是告诉编译器,在编译阶段不需要实现setter、getter方法;可以在运行时,创建setter、getter方法
//@dynamic name;
- (void)setName:(NSString *)name{
//第一种方法 保存到临时文件中
[name writeToFile:FILEPATH atomically:YES encoding:NSUTF8StringEncoding error:NULL];
//第二种方法 运行时方法
objc_setAssociatedObject(self, @"name", name, 0);
}
- (NSString *)name{
//第一种方法 从临时文件中读取
return [NSString stringWithContentsOfFile:FILEPATH encoding:NSUTF8StringEncoding error:NULL];
//第二种方法 运行时方法
return objc_getAssociatedObject(self, @"name");
}
@end
(因为分类中不会自动生成带下划线的成员变量,因此要另想办法保存数据和读取数据)
4、属性修饰符
/*
copy 方法:
类型 是否产生新的对象 是否可变
NSString no no
NSMutableString yes no
NSArray no no
NSMutableArray yes no
mutableCopy 方法:
类型 是否产生新的对象 是否可变
NSString yes yes
NSMutableString yes yes
NSArray yes yes
NSMutableArray yes yes
*/
/*
retain:MRC 对对象使用 引用计数器 +1
assign:MRC/ARC 对基本数据类型
weak:ARC 弱指针 解决循环引用 控制器引用UI控件的时候使用
strong:ARC 强指针
*/