iOS animation动画三个角色(下)

tags: Animation


上篇iOS animation动画三个角色(上)介绍了主角CALayer和几个动画剧本。本篇以几个小例子配以武功秘籍继续介绍其他主角

  • 形状图层 CAShapeLayer 绘制不规则图形(太极拳)
  • 渐变图层 CAGradientLayer 颜色渐变、阴影(隐身术)
  • 复制图层 CAReplicatorLayer 迭代复制同一个图层(分身术)

CAShapeLayer 太极圈

继承自CALayer,因此,可使用CALayer的所有属性。但是,CAShapeLayer需要和贝塞尔曲线配合使用才有意义。

关于UIBezierPath

path:表示路径,可以用贝塞尔曲线,也可以自定义路径
fillcolor:表示填充色
strokeColor:线条颜色
linewidth:线的宽度
strokeStart:stroke的起始点(0~1)
strokeEnd:stroke的结束点(0~1)
实例

@interface ProgressView : UIView
@end
@implementation ProgressView
-(id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        CAShapeLayer * shapelayer = [CAShapeLayer layer];
    
        UIBezierPath * path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(frame.size.width/2, frame.size.height/2) radius:frame.size.width/2 startAngle:0 endAngle:2*M_PI clockwise:YES];
        //[UIBezierPath bezierPathWithRoundedRect:frame cornerRadius:frame.size.width/2];
        //路径
        shapelayer.path = path.CGPath;
        //填充色
        shapelayer.fillColor = [UIColor clearColor].CGColor;
        // 设置线的颜色
        shapelayer.strokeColor = [UIColor orangeColor].CGColor;
        //线的宽度
        shapelayer.lineWidth = 5;
        [self.layer addSublayer:shapelayer];
        
        //设置stroke起始点
//        shapelayer.strokeStart = 0;
//        shapelayer.strokeEnd = 0.75;
        
        CABasicAnimation * anima = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
        anima.fromValue = [NSNumber numberWithFloat:0.f];
        anima.toValue = [NSNumber numberWithFloat:1.f];
        anima.duration = 4.0f;
        anima.repeatCount = MAXFLOAT;
        anima.timingFunction = UIViewAnimationOptionCurveEaseInOut;
        [shapelayer addAnimation:anima forKey:@"strokeEndAniamtion"];
 
        
        CABasicAnimation *anima3 = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
        anima3.toValue = [NSNumber numberWithFloat:-M_PI*2];
        anima3.duration = 2.0f;
        anima3.repeatCount = MAXFLOAT;
        anima3.timingFunction = UIViewAnimationOptionCurveEaseInOut;
        [self.layer addAnimation:anima3 forKey:@"rotaionAniamtion"];
    }
    return self;
}
@end

演示图


shapeloading

CAGradientLayer 隐身术,渐变术

继承calayer,主要用于处理颜色渐变的图层。主要有以下的Properties

@property(copy) NSArray *colors
渐变颜色的数组
注意这几个数字在0到1之间单调递增。
@property CGPoint startPoint
映射locations中第一个位置,用单位向量表示,比如(0,0)表示从左上角开始变化。默认值是(0.5,0.0)。
@property CGPoint endPoint
映射locations中最后一个位置,用单位向量表示,比如(1,1)表示到右下角变化结束。默认值是(0.5,1.0)。
@property(copy) NSString *type
默认值是kCAGradientLayerAxial,表示按像素均匀变化。除了默认值也无其它选项。

//做颜色渐变
-(void)testslidetounlock
{
    UILabel * textLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 100, 200, 30)];
    textLabel.center = self.view.center;
    textLabel.textColor = [UIColor colorWithWhite:1 alpha:0.8];
    textLabel.textAlignment = NSTextAlignmentCenter;
    textLabel.text = @">> 滑动来解锁 >>>";
    [self.view addSubview:textLabel];

    CAGradientLayer *gradient = [CAGradientLayer layer];
//    gradient.backgroundColor = [UIColor grayColor].CGColor;
    gradient.frame = textLabel.bounds;
    UIColor *startColor = [UIColor whiteColor];
    UIColor *endColor   = [UIColor clearColor];
    gradient.colors = @[(id)endColor.CGColor,(id)startColor.CGColor, (id)endColor.CGColor];
    gradient.startPoint = CGPointMake(0, 0);//(左,下)
    gradient.endPoint = CGPointMake(1, 0);//(右,下)
//    [textLabel.layer insertSublayer:gradient atIndex:0];
    gradient.locations = @[@.2,@.5,@.8];
    
    textLabel.layer.mask = gradient;
    CABasicAnimation * gradientanimation = [CABasicAnimation animationWithKeyPath:@"locations"];
    gradientanimation.fromValue = @[@0, @0,@0.25];
    gradientanimation.toValue = @[@0.75,@1 ,@1];
    gradientanimation.duration = 2.5;
    gradientanimation.repeatCount = HUGE;
    [gradient addAnimation:gradientanimation forKey:@"gradientanimation"];//gradient, forKey: nil)
}

演示图


滑动开锁动画

CAReplicatorLayer 分身术

复制器图层(观音送给孙悟空的三根毫毛,吹一下就变成无数的猴子猴孙)
CAReplicatorLayer是一个容器层
复制自己子层的layer,并且复制的出来的layer和原来的子layer拥有相同的动效。然后通过设置一些属性,可以设置其偏移位置让其依次排列,也可以设置不同的触发时间这样就形成了动画的效果
常用于做loading动画

repicator例子

此处包含两个动画,一个是正在播放的状态动画,一个是加载的动画

播放状态动画

@interface PlayingAnimationView : UIView
@end

@implementation PlayingAnimationView

-(id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        CAReplicatorLayer * replicatorLayer = [CAReplicatorLayer new];
        replicatorLayer.bounds = CGRectMake(0, 0, frame.size.width, frame.size.height); 
        replicatorLayer.anchorPoint = CGPointMake(0, 0);
        [self.layer addSublayer:replicatorLayer];
        
        CALayer * rectangle = [CALayer new];
        CGFloat width = (frame.size.width - 30)/4;
        rectangle.bounds = CGRectMake(0, 0, width, frame.size.height - 10);//: 0, y: 0, width: 30, height: 90)
        rectangle.anchorPoint = CGPointMake(0, 0);
        rectangle.position = CGPointMake(frame.origin.x + 10, frame.origin.y + 110);
        rectangle.cornerRadius = 2;
        rectangle.backgroundColor = [UIColor whiteColor].CGColor;
        [replicatorLayer addSublayer:rectangle];
    
        
        CABasicAnimation * moveRectangle = [CABasicAnimation animationWithKeyPath:@"position.y"];
        moveRectangle.toValue = @(rectangle.position.y - 70);
        moveRectangle.duration = 0.7;
        moveRectangle.autoreverses = true;
        moveRectangle.repeatCount = HUGE;
        
        [rectangle addAnimation:moveRectangle forKey:nil];
        
        //复制动画和状态
        //重复次数
        replicatorLayer.instanceCount = 4;
        //平移点的间隔 x y z
        replicatorLayer.instanceTransform = CATransform3DMakeTranslation(width + 10, 0, 0);
        replicatorLayer.masksToBounds = true;
        replicatorLayer.instanceDelay =0.3;//延迟动画开始时间 以造成上下移动的效果 
    }
    return self;
}
@end

我们观察到主要CAReplicatorLayer可以对它自己的子Layer进行复制操作。创建了CAReplicatorLayer实例后,设置了它的尺寸大小、位置、锚点位置、背景色,并且将它添加到了replicatorAnimationView的Layer中。
CAReplicatorLayer.h
中文翻译如下:

复制器层创建的副本指定数量的其子层,每个副本都可能有几何,时间和适用于它的颜色变换。

名称 功能
instanceCount 要创建的副本个数(默认一个)
preservesDepth 是否将3D例子系统平面化到一个图层(默认NO)
instanceDelay 动画时间延迟。默认为0
instanceTransform 迭代图层的位置 CATransform3D对象(创建方法用:CATransform3DMakeRotation圆形排列,CATransform3DMakeTranslation水平排列)
instanceColor 颜色组件添加到实例k - 1产生的颜色实例的调制颜色k。清晰的颜色(默认不透明白色)
instanceRedOffset,instanceGreenOffset,instanceBlueOffset,instanceAlphaOffset 加到实例K-1的颜色的颜色分量,以产生实例k的调制颜色。默认为鲜明的色彩(无变化)。

等待加载动画

@interface LoadingView : UIView
@end
@implementation LoadingView
-(id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        CAReplicatorLayer * replicatorLayer = [CAReplicatorLayer new];
        replicatorLayer.bounds = CGRectMake(0, 0, frame.size.width, frame.size.height);
        replicatorLayer.position = CGPointMake(frame.size.width/2, frame.size.height/2);
        [self.layer addSublayer:replicatorLayer];
        CALayer * circle = [CALayer new];
        circle.bounds = CGRectMake(0, 0, 15, 15);
        circle.position = CGPointMake(frame.size.width/2, frame.size.height/2 - 55);
        circle.cornerRadius = 7.5;
        circle.backgroundColor = [UIColor whiteColor].CGColor;
        [replicatorLayer addSublayer:circle];
        //复制15个同样的layer
        replicatorLayer.instanceCount = 15;
        CGFloat angle = 2 * M_PI/ 15.;
        replicatorLayer.instanceTransform = CATransform3DMakeRotation(angle, 0, 0, 1);
        replicatorLayer.instanceDelay = 1./15.;//延迟动画开始时间 以造成旋转的效果
     
        CABasicAnimation *scale = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
        scale.fromValue = @1;
        scale.toValue = @0.1;
        scale.duration = 1;
        scale.repeatCount = HUGE;
        circle.transform = CATransform3DMakeScale(0.01, 0.01, 0.01);
        [circle addAnimation:scale forKey:nil];
    }
    return self;
}
@end

总结:结合上篇文章体会一下,一些原来看起来很复杂的动画其实挺简单的。主要是要分解出最原始的状态,如果有重复就像孙悟空一样拔一根毫毛变出很多的猴子猴孙出来,一个大片用了这些主角,有了剧本,作为程序猿的你这个导演可以开拍大片了。


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

推荐阅读更多精彩内容