用CABasicAnimation/CAKeyframeAnimation画一些简单的动画(直线/渐变圆环/波浪等)

前面通过UIBezierPath画了一些简单的集合图形,这些图形是固定的,并不是动画!这次就通过CABasicAnimation/CAKeyframeAnimation画一些简单的动画(CABasicAnimation只是简单的,个人认为可以理解成CAKeyframeAnimation只规定起点和终点),废话不多说,直接上代码 (底部附有Demo地址)
效果如下


2222.gif

1:画一条直线

//画一个直线动画
-(void)creatLineAnimation{
    
    UIBezierPath *path = [UIBezierPath bezierPath];
    //要画的线的起始点
    [path moveToPoint:CGPointMake(10, 100)];
    //线的终点
    [path addLineToPoint:CGPointMake(300, 100)];
    
    CAShapeLayer *layer = [CAShapeLayer layer];
    layer.path = path.CGPath;
    layer.lineWidth = 2;
    layer.strokeColor = [UIColor blackColor].CGColor;
    layer.fillColor = [UIColor clearColor].CGColor;
    /*
     加上这句代码就把直线编程虚线了(数组里面为虚线的每段长度)
     如果为多个值,则会进行循环画相应长度的虚线
     */
//    layer.lineDashPattern =@[@(10)];
    
    
    /*
     CABasicAnimation:只针对起点和终点进行动画,可以理解成CAKeyframeAnimation只设置起点和终点
     strokeStart:从起始点都结尾点  消除线
     strokeEnd:从起始点到结束点  画线
     */
    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
    //.动画时长
    animation.duration = 5;
    /*
     fromValue/toValue  起始/结束(0-1)
     fromValue:相当于从直线的哪个位置开始执行动画
     toValue:动画结束在线的哪个位置
     */
    animation.fromValue = @(0);
    animation.toValue = @(1);
    //动画重复次数
    animation.repeatCount = 1;
    //保持线的最终状态
    animation.fillMode = kCAFillModeForwards;
    //动画添加到CAShapeLayer上
    [layer addAnimation:animation forKey:nil];
    //layer展示到视图上
    [self.layer addSublayer:layer];
}

2:画一个渐变的圆

/*
 画一个渐变圆环(其实就是建一个view,给view加上一个渐变背景色,然后画圆环,设置view.layer.mask 加上一层蒙版,和控件切圆一样的思路,最后加上CAGradientLayer的动画,就形成一个渐变色圆环的动画)
 */
-(void)creatCircle{
    //设置底层View
    UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 100, self.frame.size.width, 120)];
    [self addSubview:view];
    //通过贝塞尔曲线画圆环
    UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(self.frame.size.width/2, 60) radius:50 startAngle:-2*M_PI endAngle:0 clockwise:YES];
    //把贝塞尔曲线画的圆环展示出来
    CAShapeLayer *layer = [CAShapeLayer layer];
    layer.lineWidth = 10;
    //这个颜色可以随便设置
    layer.strokeColor = [UIColor redColor].CGColor;
    //因为默认填充色为黑色  所以把填充色规定为白色
    layer.fillColor = [UIColor clearColor].CGColor;
    layer.path = path.CGPath;
    [view.layer addSublayer:layer];
    
    CAGradientLayer *gradient = [CAGradientLayer layer];
    gradient.frame = view.bounds;
    //背景色起始点 z左上角为(0.0)
    gradient.startPoint = CGPointMake(0, 0);
    //背景色终点
    gradient.endPoint = CGPointMake(1, 1);
    //设置所有的渐变颜色
    gradient.colors = @[(__bridge id)[UIColor blueColor].CGColor,(__bridge id)[UIColor redColor].CGColor,(__bridge id)[UIColor blackColor].CGColor,(__bridge id)[UIColor yellowColor].CGColor];
    //设置颜色区间点位置(相当于把圆环看成1 然后各个颜色在圆环的位置)
    gradient.locations = @[@(.25),@(.5),@(.8),@(1)];
    //设置底层View的渐变色
    [view.layer addSublayer:gradient];
    //给view加蒙板(蒙板就是展示贝塞尔曲线画出来圆环的CAShapeLayer)
    view.layer.mask = layer;
    //添加动画
    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
    animation.fromValue = @(0);
    animation.toValue =@(1);
    animation.duration = 5;
    [layer addAnimation:animation forKey:@""];
}

3:画一个围绕圆环转的小动画

/*
 围着圆环转的小圆点
 1:先通过贝塞尔曲线画一个圆环
 2:创建一个view(任何控件都可以)切圆
 3:加载CAKeyframeAnimation 动画
 */
-(void)creatCAKeyframeAnimationDemo{
    //创建圆环
    UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(self.frame.size.width/2, 450) radius:50 startAngle:-2*M_PI endAngle:0 clockwise:YES];
    
    CAShapeLayer *layer = [CAShapeLayer layer];
    layer.lineWidth = 3;
    layer.strokeColor = [UIColor blackColor].CGColor;
    layer.fillColor = [UIColor clearColor].CGColor;
    layer.path = path.CGPath;
    [self.layer addSublayer:layer];
    //创建view(围着圆转的红色小圆点)
    UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 30, 30)];
    view.backgroundColor = [UIColor redColor];
    [self addSubview:view];
    //给创建的view切圆
    UIBezierPath *criclePath = [UIBezierPath bezierPathWithRoundedRect:view.bounds byRoundingCorners:UIRectCornerAllCorners cornerRadii:CGSizeMake(view.frame.size.width/2, view.frame.size.height/2)];
    CAShapeLayer *cricleLayer = [CAShapeLayer layer];
    cricleLayer.path = criclePath.CGPath;
    view.layer.mask = cricleLayer;
    
    //添加动画使其围绕着圆环转
    CAKeyframeAnimation *animation = [CAKeyframeAnimation animation];
    //这里是围着贝塞尔曲线转的 所以keyPath设置为position
    animation.keyPath = @"position";
    animation.path = path.CGPath;
    animation.duration = 10;
    //无限转
    animation.repeatCount = HUGE;
    //把动画加载到创建的view上(让圆点到圆环上切转动都在此处完成)
    [view.layer addAnimation:animation forKey:@""];
}

4:画一个简单的波浪

//创建波浪线的承载以及帧的刷新
-(void)creatCurve{
    
    self.shapeLayer = [CAShapeLayer layer];
    self.shapeLayer.frame = CGRectMake(0, 250, self.frame.size.width, 200);
    self.shapeLayer.fillColor = [UIColor blueColor].CGColor;
    [self.layer addSublayer:self.shapeLayer];
    /*
     CADisplayLink:和计时器差不多 不过这个是按照帧数去刷新 才能看出来波浪一直在动(具体区别自行百度)
     */
    CADisplayLink *link = [CADisplayLink displayLinkWithTarget:self selector:@selector(showAnimation)];
    /*
     link:加入到指定的runloop中 NSRunLoopCommonModes加入到这个中,可以使这个按帧数刷新不受页面变化的影响(NSRunLoopCommonMode这个会受到页面滚动等等因素的影响,具体差别自行百度)
     */
    [link addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
    
    self.offset = 0;
}
//创建波浪线及其动态
-(void)showAnimation{
    //创建可变的路径
    CGMutablePathRef path = CGPathCreateMutable();
    
    //规定波浪浮动的高度
    CGFloat y=50;
    //要绘制路径的起始点
    CGPathMoveToPoint(path, nil, 0, y);
    //循环整个屏幕宽度的像素点(具体根据自己需要宽度自行设置)
    for (int i = 0; i<self.frame.size.width; i++) {
        //算出波浪线各个点所在的位置
        y = 10*sin((1/50.0)*i+self.offset);
        //把算出的的点连成线
        CGPathAddLineToPoint(path, nil, i, y);
    }
    //这两个方法是为了下面的整体蓝色部分,使看着更像波浪线(可以屏蔽这两个划线方法  看看实际效果)
    CGPathAddLineToPoint(path, nil, self.frame.size.width, 100);
    CGPathAddLineToPoint(path, nil, 0, 100);
    //闭合整个路径
    CGPathCloseSubpath(path);
    //把该路径通过CAShapeLayer呈现出来(类似呈现贝塞尔所画的线的路径)
    self.shapeLayer.path = path;
    //递减保留的图形路径计数 (我个人认为可以理解成释放(要是有错误麻烦大佬指正))
    CGPathRelease(path);
    //
    self.offset +=0.1;
    if (self.offset>200*M_PI) {
        self.offset = 0;
    }
    
}

Demo地址:https://github.com/xiaoxie0217/UIBezier

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,002评论 6 509
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,777评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,341评论 0 357
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,085评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,110评论 6 395
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,868评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,528评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,422评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,938评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,067评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,199评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,877评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,540评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,079评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,192评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,514评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,190评论 2 357

推荐阅读更多精彩内容