美文网首页程序员
Objective-C,从0开始写一个自定义加载动画

Objective-C,从0开始写一个自定义加载动画

作者: 忠橙_g | 来源:发表于2016-12-27 17:09 被阅读168次

今天在精选 20 个优质的加载动画中发现了一个蛮有意思的加载动画:

效果图
正好最近原来的加载动画用的腻了😄
所以决定用OC实现一下这个动画来用看看。
那么我们开始

首先,分析一下这个动画:

1.元素分析

从gif上看,主体由一个盒子(三角形的洞)和一些飘落的元素组成(下方的字表示😢)。

2.动画分析

我们看到飘落的字从红框的位置随机出现,然后落向黄线的随机位置消失,同时透明度也从0开始变成1。

分析图

动画过程中,伴随着不同的角速度进行旋转,下落的速度也各不相同。
因此我们需要准备以下几个方法来实现动画效果:
1.产生随机的起点坐标
2.产生随机的终点坐标
3.产生随机的速度、角速度
4.实现位移、旋转、透明度改变的动画
从上面的分析来看,要实现这个效果并不是很困难😳。
So,Les's do it.

3.需要用到的知识储备

Core Animation
然后...嗯...貌似就够了...

4.代码实现

1.随机产生起点和终点坐标

//获取起点坐标
- (CGPoint)randomBeginPoint{
    return [self getRandomFrameInRect:CGRectMake(0, 0, self.frame.size.width, 10)];
}

//获取终点坐标
- (CGPoint)randomEndPoint{
    return [self getRandomFrameInRect:CGRectMake(0, self.frame.size.height - 20, self.frame.size.width, 10)];
}

//方形区域内产生随机点
- (CGPoint)getRandomFrameInRect:(CGRect)rect{
    CGFloat minX = rect.origin.x;
    CGFloat width = rect.size.width;
    CGFloat minY = rect.origin.y;
    CGFloat height = rect.size.height;
    //产生随机数
    CGFloat randomX = minX + (float)(arc4random() % (int)width);
    CGFloat randomY = minY + (float)(arc4random() % (int)height);
    return CGPointMake(randomX, randomY);
}

2.产生随机的角速度与下落速度
下落速度:通过下落到终点所需时间(即动画时间)设定
角速度:下落到终点时旋转的角度 和 动画时间 共同决定旋转的角速度

//获取随机的动画时间
- (CGFloat)getRandomDuration{
    //产生随机数(这里我们定义的动画时间为0.5s~1.0s)
    int time = arc4random()%50 + 50;
    CGFloat duration = time/100;
    return duration;
}

//获取随机的角度
- (CGFloat)getRandomRotation{
    //产生随机数(这里我们定义的旋转角度范围为 -180度~180度)
    int angle = arc4random()%360 - 180;
    CGFloat rotation = angle*180/M_PI;
    return rotation;
}

3.产生动画的方法

- (void)addAnimationToLayer:(CALayer*)layer{
    //获取随机参数
    CGFloat duration = [self getRandomDuration];
    CGFloat rotation = [self getRandomRotation];
    CGPoint beginPoint = [self getRandomBeginPoint];
    CGPoint endPoint = [self getRandomEndPoint];
    
    //平移
    CABasicAnimation *positionAnim = [CABasicAnimation animationWithKeyPath:@"position"];
    positionAnim.duration = duration;
    positionAnim.fromValue = [NSValue valueWithCGPoint:beginPoint];
    positionAnim.toValue = [NSValue valueWithCGPoint:endPoint];
    positionAnim.fillMode = kCAFillModeForwards;
    
    //旋转
    CABasicAnimation *transformAnim = [CABasicAnimation animationWithKeyPath:@"transform"];
    transformAnim.duration = duration;
    // 绕着(0, 0, 1)这个向量轴顺时针旋转rotation
    transformAnim.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeRotation(rotation, 0, 0, 1)];
    
    //透明度
    CABasicAnimation *opacityAnimation =[CABasicAnimation animationWithKeyPath:@"opacity"];
    opacityAnimation.fromValue = @0.f;
    opacityAnimation.toValue = @1.f;
    opacityAnimation.duration = duration;
    opacityAnimation.fillMode = kCAFillModeForwards;
    
    [layer addAnimation:positionAnim forKey:@"lposition"];
    [layer addAnimation:transformAnim forKey:@"ltransform"];
    [layer addAnimation:opacityAnimation forKey:@"lopacity"];
    layer.opacity = 0;

    //循环动画
    if (animation) {
        [self performSelector:@selector(addAnimationToLayer:) withObject:layer afterDelay:duration];
    }
}

4.测试一下动画的效果

UILabel *label = [[UILabel alloc]init];
label.text = @"0";
label.font = [UIFont systemFontOfSize:20];
label.textColor = [UIColor whiteColor];
[label sizeToFit];
[self addSubview:label];
[self addAnimationToLayer:label.layer];

5.循环动画
增加一个属性animation来判断是否循环执行动画(这样如果要停止循环只要把它设置为NO就好了),然后在addAnimationToLayer:添加循环调用的方法:

//循环动画
    if (_animation) {
        [self performSelector:@selector(addAnimationToLayer:) withObject:layer afterDelay:duration];
    }

6.添加细节
经过上面的过程,动画的效果已经解决了。
接下来就是产生4个元素,再加上下面终点的图片,基本上就可以达到想要的效果了。
上图:


效果图

好了 今天先实现到这里,后续有空到话再继续优化,代码已经上传到GZCLoding,如果有什么建议,欢迎留言告诉我哦。

相关文章

网友评论

    本文标题:Objective-C,从0开始写一个自定义加载动画

    本文链接:https://www.haomeiwen.com/subject/eqckvttx.html