0829-0616 动画
--------------------
CALayer
手动创建的layer 修改某些属性 默认有动画 头文件中看到属性描述有animatin的都是有默认动画的
- (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. CALayer *layer = [CALayer layer]; layer.backgroundColor = [UIColor redColor].CGColor; layer.bounds = CGRectMake(0, 0, 100, 100); layer.anchorPoint = CGPointZero; [self.view.layer addSublayer:layer]; self.layer = layer; } - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { // 关闭隐式动画 // [CATransaction begin]; // [CATransaction setDisableActions:YES]; // 隐式动画 self.layer.backgroundColor = [UIColor greenColor].CGColor; // self.layer.bounds = CGRectMake(0, 0, 200, 200); self.layer.position = CGPointMake(200, 200); // self.layer.position // 如何查看CALayer的某个属性是否支持隐式动画, 查看头文件是否有 Animatable // [CATransaction commit]; } @end
--------------
自定义Layer
了解即可
1、自定义layer 需要手动调用 setNeedsdisplay 来调用drawRect方法
[mylayer setNeedsdisplay]
[self.view layer addSublayer:myLayer];
2、自定义layer设置delegate 那么setNeedsDisplay方法会调用delegate的drawLayer方法
---------------
核心动画 用的最多的一个子类是CATransition转场动画效果 只能适用于作用于CALayer
【【【
// // NJViewController.m // 03-基本动画 #import "NJViewController.h" #import <QuartzCore/QuartzCore.h> @interface NJViewController () @property (nonatomic, strong) CALayer *myLayer; @end @implementation NJViewController - (void)viewDidLoad { [super viewDidLoad]; // 1.创建layer CALayer *myLayer = [CALayer layer]; myLayer.bounds = CGRectMake(0, 0, 100, 100); myLayer.anchorPoint = CGPointZero; myLayer.position = CGPointMake(100, 100); myLayer.backgroundColor = [UIColor greenColor].CGColor; // 2.将自定义Layer添加到控制器的view的layer上 [self.view.layer addSublayer:myLayer]; self.myLayer = myLayer; } - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { // 1. 创建核心动画 CABasicAnimation *anima = [CABasicAnimation animation] ; // 1.1设置动画类型 // anima.keyPath = @"transform.translation.x"; anima.keyPath = @"transform.scale.y"; // 1.2 设置动画执行完毕之后不删除动画 anima.removedOnCompletion = NO; // 1.3 设置保存动画的最新状态 anima.fillMode = kCAFillModeForwards; // 1.4设置动画时间 anima.duration = 1; // 1.5如何动画 // anima.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeTranslation(0, 100, 1)]; // anima.toValue = @(100); anima.toValue = @(1.5); // 2.添加核心动画到Layer [self.myLayer addAnimation:anima forKey:nil]; } - (void)test2 { // 1. 创建核心动画 CABasicAnimation *anima = [CABasicAnimation animation] ; // 1.1设置动画类型 anima.keyPath = @"transform"; // 1.2 设置动画执行完毕之后不删除动画 anima.removedOnCompletion = NO; // 1.3 设置保存动画的最新状态 anima.fillMode = kCAFillModeForwards; // 1.4设置动画时间 anima.duration = 1; // 1.5修改动画 anima.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeRotation(M_PI_4, 0, 0, 1)]; // 2.添加核心动画到Layer [self.myLayer addAnimation:anima forKey:nil]; } - (void)test1 { // 1. 创建核心动画 CABasicAnimation *anima = [CABasicAnimation animation] ; // 1.1设置动画类型 anima.keyPath = @"bounds"; // 1.2 设置动画执行完毕之后不删除动画 anima.removedOnCompletion = NO; // 1.3 设置保存动画的最新状态 anima.fillMode = kCAFillModeForwards; // 1.4设置动画时间 anima.duration = 1; // 1.5修改动画 anima.toValue =[NSValue valueWithCGRect: CGRectMake(0, 0, 200, 200)]; // 2.添加核心动画到Layer [self.myLayer addAnimation:anima forKey:nil]; } - (void)test { // 1. 创建核心动画 CABasicAnimation *anima = [CABasicAnimation animation] ; // 1.1告诉系统要执行什么样的动画 anima.keyPath = @"position"; // 设置通过动画将layer从哪 // anima.fromValue = [NSValue valueWithCGPoint:CGPointMake(0, 0)]; // 到哪(到指定的位置) anima.toValue = [NSValue valueWithCGPoint:CGPointMake(200, 300)]; // 在当前位置的基础上增加多少 // anima.byValue = [NSValue valueWithCGPoint:CGPointMake(0, 300)]; // 设置动画时间 anima.duration = 5; // 1.2 设置动画执行完毕之后不删除动画 anima.removedOnCompletion = NO; // 1.3 设置保存动画的最新状态 anima.fillMode = kCAFillModeForwards; // 2.添加核心动画到Layer [self.myLayer addAnimation:anima forKey:nil]; } @end
// NJViewController.m // 04-关键帧动画 #import "NJViewController.h" @interface NJViewController () @property (weak, nonatomic) IBOutlet UIView *customView; - (IBAction)btnClick:(id)sender; @end @implementation NJViewController - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { [self test]; // [self test1]; } - (void)test1 { // 1.创建核心动画 CAKeyframeAnimation *keyAnima = [CAKeyframeAnimation animation]; // 1.1告诉系统执行什么动画 keyAnima.keyPath = @"position"; CGMutablePathRef path = CGPathCreateMutable(); CGPathAddEllipseInRect(path, NULL, CGRectMake(0, 100, 200, 200)); keyAnima.path = path; CGPathRelease(path); // 1.2保存执行完之后的状态 // 1.2.1执行完之后不删除动画 keyAnima.removedOnCompletion = NO; // 1.2.2执行完之后保存最新的状态 keyAnima.fillMode = kCAFillModeForwards; // 1.3设置动画时间 keyAnima.duration = 2; // 2.观察动画什么时候开始执行, 以及什么时候执行完毕 keyAnima.delegate = self; // 3.添加核心动画 [self.customView.layer addAnimation:keyAnima forKey:@"abc"]; } - (IBAction)btnClick:(id)sender { // 停止动画 [self.customView.layer removeAnimationForKey:@"abc"]; } - (void)test { // 1.创建核心动画 CAKeyframeAnimation *keyAnima = [CAKeyframeAnimation animation]; // 1.1告诉系统执行什么动画 keyAnima.keyPath = @"position"; // NSValue *v1 = [NSValue valueWithCGPoint:CGPointMake(0, 100)]; NSValue *v2 = [NSValue valueWithCGPoint:CGPointMake(100, 100)]; NSValue *v3 = [NSValue valueWithCGPoint:CGPointMake(100, 200)]; NSValue *v4 = [NSValue valueWithCGPoint:CGPointMake(0, 200)]; NSValue *v5 = [NSValue valueWithCGPoint:CGPointMake(0, 100)]; keyAnima.values = @[v2, v3, v4, v5]; // keyAnima.keyTimes = @[@(0.5) ,@(0.5), @(0.5)]; keyAnima.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; // 1.2保存执行完之后的状态 // 1.2.1执行完之后不删除动画 keyAnima.removedOnCompletion = NO; // 1.2.2执行完之后保存最新的状态 keyAnima.fillMode = kCAFillModeForwards; // 1.3设置动画时间 keyAnima.duration = 2; // 2.观察动画什么时候开始执行, 以及什么时候执行完毕 keyAnima.delegate = self; // 2.添加核心动画 [self.customView.layer addAnimation:keyAnima forKey:nil]; } - (void)animationDidStart:(CAAnimation *)anim { NSLog(@"animationDidStart"); } - (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag { NSLog(@"animationDidStop"); } @end
// NJViewController.m // 05-图标抖动 #import "NJViewController.h" #define angle2Radian(angle) ((angle) / 180.0 * M_PI) @interface NJViewController () @property (weak, nonatomic) IBOutlet UIImageView *iconView; @end @implementation NJViewController - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { // 1.创建核心动画 CAKeyframeAnimation *keyAnima = [CAKeyframeAnimation animation]; keyAnima.keyPath = @"transform.rotation"; // 度数 / 180 * M_PI keyAnima.values = @[@(-angle2Radian(4)), @(angle2Radian(4)), @(-angle2Radian(4))]; keyAnima.removedOnCompletion = NO; keyAnima.fillMode = kCAFillModeForwards; keyAnima.duration = 0.1; // 设置动画重复的次数 keyAnima.repeatCount = MAXFLOAT; // 2.添加核心动画 [self.iconView.layer addAnimation:keyAnima forKey:nil]; } @end
--
转场动画
// NJViewController.m // 06-转场动画 #import "NJViewController.h" @interface NJViewController () @property (weak, nonatomic) IBOutlet UIImageView *iconView; - (IBAction)nextBtnClick:(id)sender; - (IBAction)preBtnClick:(id)sender; @property (nonatomic, assign) int index; @end @implementation NJViewController // 下一张 - (IBAction)nextBtnClick:(id)sender { self.index++; if (self.index >7) { self.index = 1; } NSString *imageName = [NSString stringWithFormat:@"%d.jpg", self.index]; UIImage *newImage = [UIImage imageNamed:imageName]; self.iconView.image = newImage; // 1.创建核心动画 CATransition *ca = [CATransition animation]; // 1.1动画过渡类型 ca.type = @"cube"; // 1.2动画过渡方向 ca.subtype = kCATransitionFromRight; // 1.3动画起点(在整体动画的百分比) // ca.startProgress = 0.5; ca.endProgress = 0.5; // 动画时间 ca.duration = 1; // 2.添加核心动画 [self.iconView.layer addAnimation:ca forKey:nil]; } // 上一张 - (IBAction)preBtnClick:(id)sender { self.index--; if (self.index < 1) { self.index = 7; } NSString *imageName = [NSString stringWithFormat:@"%d.jpg", self.index]; UIImage *newImage = [UIImage imageNamed:imageName]; self.iconView.image = newImage; // 1.创建核心动画 CATransition *ca = [CATransition animation]; // 1.1告诉系统执行什么动画 ca.type = @"cube"; ca.subtype = kCATransitionFromLeft; ca.duration = 1; // 2.添加核心动画 [self.iconView.layer addAnimation:ca forKey:nil];//forKey 是这个动画的标识 以后可以通过这个标识remove这个动画 } @end
--
组动画
// // NJViewController.m // 07-组动画 #import "NJViewController.h" @interface NJViewController () @property (weak, nonatomic) IBOutlet UIView *iconView; @end @implementation NJViewController - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { // 平移动画 CABasicAnimation *a1 = [CABasicAnimation animation]; a1.keyPath = @"transform.translation.y"; a1.toValue = @(100); // 缩放动画 CABasicAnimation *a2 = [CABasicAnimation animation]; a2.keyPath = @"transform.scale"; a2.toValue = @(0.0); // 旋转动画 CABasicAnimation *a3 = [CABasicAnimation animation]; a3.keyPath = @"transform.rotation"; a3.toValue = @(M_PI_2); // 组动画 CAAnimationGroup *groupAnima = [CAAnimationGroup animation]; groupAnima.animations = @[a1, a2, a3]; groupAnima.duration = 2; groupAnima.fillMode = kCAFillModeForwards; groupAnima.removedOnCompletion = NO; [self.iconView.layer addAnimation:groupAnima forKey:nil]; } @end
】】】
-------------
Core animation
跨平台 后台操作 不阻塞线程 直接作用于CALayer
QuartzCore框架
动画类继承关系CAAnimation是抽象类
这个在ppt里有 ios开发文档没这个属性 type属性
/* 过渡效果 fade //交叉淡化过渡(不支持过渡方向) kCATransitionFade push //新视图把旧视图推出去 kCATransitionPush moveIn //新视图移到旧视图上面 kCATransitionMoveIn reveal //将旧视图移开,显示下面的新视图 kCATransitionReveal cube //立方体翻滚效果 oglFlip //上下左右翻转效果 suckEffect //收缩效果,如一块布被抽走(不支持过渡方向) rippleEffect //滴水效果(不支持过渡方向) pageCurl //向上翻页效果 pageUnCurl //向下翻页效果 cameraIrisHollowOpen //相机镜头打开效果(不支持过渡方向) cameraIrisHollowClose //相机镜头关上效果(不支持过渡方向) */
CALayer 核心动画 用的最多的就是 转场动画
实际开发中我们不用CALayer核心动画 而是用UIView自带的动画
[UIView begin…block
因为动画执行结束不会反弹 frame位置真实改变 内部也封装了核心动画的转场动画
但是唯一缺点就是转场动画的选项只有几个
而CALayer会反弹 需要设定为不反弹 不结束 frame位置其实没有改变
-------------
UIView封装的核心动画 应用最广
// NJViewController.m // 07-UIView封装动画 #import "NJViewController.h" @interface NJViewController () @property (weak, nonatomic) IBOutlet UIView *cutomView; @end @implementation NJViewController - (void)viewDidLoad { [super viewDidLoad]; } - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { [UIView transitionWithView:self.view duration:1.0 options:0 animations:^{ NSLog(@"animations"); // 要执行的动画 [UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:self.view cache:YES]; } completion:^(BOOL finished) { NSLog(@"completion"); // 执行完毕之后执行的动画 }]; } - (void)test2 { [UIView animateWithDuration:2.0 animations:^{ NSLog(@"动画执行之前: %@",NSStringFromCGPoint(self.cutomView.center)); // 需要执行动画的代码 self.cutomView.center = CGPointMake(300, 300); } completion:^(BOOL finished) { // 动画执行完毕之后执行的代码 NSLog(@"动画执行之后: %@",NSStringFromCGPoint(self.cutomView.center)); }]; } - (void)test1 { // 1.创建核心动画 // 注意点:如果通过核心动画改变layer的位置状态, 表面上看上去已经改变了, 但是实质上是没有改变的 CABasicAnimation *anima = [CABasicAnimation animation]; anima.keyPath = @"position"; anima.toValue = [NSValue valueWithCGPoint:CGPointMake(300, 300)]; anima.removedOnCompletion = NO; anima.fillMode = kCAFillModeForwards; anima.delegate = self; // 2.添加核心动画 [self.cutomView.layer addAnimation:anima forKey:nil]; } - (void)animationDidStart:(CAAnimation *)anim { NSLog(@"核心动画执行之前 %@", NSStringFromCGPoint(self.cutomView.layer.position)); } - (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag { NSLog(@"核心动画执行完毕 %@", NSStringFromCGPoint(self.cutomView.layer.position)); } - (void)test { // 1.UIVIEW封装的动画, 动画执行完毕之后不会反弹 NSLog(@"动画执行之前: %@",NSStringFromCGPoint(self.cutomView.center)); [UIView beginAnimations:nil context:nil]; [UIView setAnimationDuration:2.0]; [UIView setAnimationDelegate:self]; [UIView setAnimationDidStopSelector:@selector(didStopAnimatino)]; self.cutomView.center = CGPointMake(300, 300); [UIView commitAnimations]; } - (void)didStopAnimatino { NSLog(@"动画执行完毕 %@", NSStringFromCGPoint(self.cutomView.center)); } @end