IOS版本-两个小球不停的绕中心旋转的进度条

转载请标明出处:

http://blog.csdn.net/hanhailong726188/article/details/47375157

本文出自:海龙的博客

一、概述

昨天实现了一个Android版本的小清新动画,可以当成进度条来用,这里补上IOS版本的



二、效果图



三、实现原理

自定义UIView,然后添加两个CALayer,通过CAShapeLayer和UIBezierPath画出两个小圆球,动起来是通过CAAnimation动画,动画包括小球的位移动画、缩放动画、透明动画组合起来的,因为涉及的东西不是很难,下面就直接贴代码了



四、代码实现

  1. TwoBallRotationProgressBar.h
//
//  TwoBallRotationProgressBar.h
//  TwoBallRotationProgressBar
//
//  Created by HailongHan on 15/8/8.
//  Copyright (c) 2015年 hhl. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface TwoBallRotationProgressBar : UIView

/**
 *  设置小球最大半径
 *
 *  @param radius 半径
 */
- (void)setBallMaxRadius:(CGFloat)radius;

/**
 *  设置小球最小半径
 *
 *  @param radius 半径
 */
- (void)setBallMinRadius:(CGFloat)radius;

/**
 *  设置俩小球颜色
 *
 *  @param oneColor 第一个小球颜色
 *  @param twoColor 第二个小球颜色
 */
- (void)setOneBallColor:(UIColor *)oneColor twoBallColor:(UIColor *)twoColor;

/**
 *  动画时间
 */
- (void)setAnimatorDuration:(CGFloat)duration;

/**
 *  设置小球移动的轨迹半径距离
 */
- (void)setAnimatorDistance:(CGFloat)distance;

- (void)startAnimator;
- (void)stopAnimator;

@end

2 . TwoBallRotationProgressBar.m

//
//  TwoBallRotationProgressBar.m
//  TwoBallRotationProgressBar
//
//  Created by HailongHan on 15/8/8.
//  Copyright (c) 2015年 hhl. All rights reserved.
//

#define DEFAULT_MAX_RADIUS 10
#define DEFAULT_MIN_RADIUS 5
#define DEFAULT_DISTANCE 15
#define DEFAULT_DURATION 1.2

#import "TwoBallRotationProgressBar.h"

@interface TwoBallRotationProgressBar ()

@property (nonatomic,assign) CGFloat maxRadius;
@property (nonatomic,assign) CGFloat minRadius;
@property (nonatomic,assign) CGFloat duration;
@property (nonatomic,assign) CGFloat distance;

@property (nonatomic,strong) CAShapeLayer *oneLayer;
@property (nonatomic,strong) CAShapeLayer *twoLayer;

@property (nonatomic,assign) Boolean isTwoAbove;

@property (nonatomic,strong) NSTimer *mTimer;

@property (nonatomic,assign) CGPoint centerPoint;

@end

@implementation TwoBallRotationProgressBar

-(instancetype)initWithFrame:(CGRect)frame{
    if (self == [super initWithFrame:frame]) {
        //TODO 初始化
        self.backgroundColor = [UIColor whiteColor];

        [self initProgressBar];
    }
    return self;
}

- (CAShapeLayer *)oneLayer{
    if (!_oneLayer) {
        _oneLayer = [CAShapeLayer layer];
        _oneLayer.frame = CGRectMake(0, 0, self.frame.size.width, self.frame.size.height);
        _oneLayer.fillColor = [UIColor redColor].CGColor;
        _oneLayer.path = [UIBezierPath bezierPathWithArcCenter:self.centerPoint radius:self.maxRadius startAngle:0 endAngle:M_PI*2 clockwise:YES].CGPath;
    }
    return _oneLayer;
}

- (CAShapeLayer *)twoLayer{
    if (!_twoLayer) {
        _twoLayer = [CAShapeLayer layer];
        _twoLayer.frame = CGRectMake(0, 0, self.frame.size.width, self.frame.size.height);
        _twoLayer.anchorPoint = CGPointMake(0.5, 0.5);
        _twoLayer.fillColor = [UIColor greenColor].CGColor;
        _twoLayer.path = [UIBezierPath bezierPathWithArcCenter:self.centerPoint radius:self.minRadius startAngle:0 endAngle:M_PI*2 clockwise:YES].CGPath;
    }
    return _twoLayer;
}

/**
 *  初始化进度条
 */
- (void)initProgressBar{
    self.isTwoAbove = YES;

    self.duration = DEFAULT_DURATION;
    self.maxRadius = DEFAULT_MAX_RADIUS;
    self.minRadius = DEFAULT_MIN_RADIUS;
    self.distance = DEFAULT_DISTANCE;

    self.centerPoint = CGPointMake(self.bounds.size.width*0.5, self.bounds.size.height*0.5);

    //添加两个CAShapeLayer
    [self.layer addSublayer:self.oneLayer];
    [self.layer addSublayer:self.twoLayer];
}

#pragma mark - 实现接口
- (void)setBallMaxRadius:(CGFloat)radius{
    self.maxRadius = radius;
    self.oneLayer.path = [UIBezierPath bezierPathWithArcCenter:self.centerPoint radius:self.maxRadius startAngle:0 endAngle:M_PI*2 clockwise:YES].CGPath;
}

- (void)setBallMinRadius:(CGFloat)radius{
    self.minRadius = radius;
    self.twoLayer.path = [UIBezierPath bezierPathWithArcCenter:self.centerPoint radius:self.minRadius startAngle:0 endAngle:M_PI*2 clockwise:YES].CGPath;
}

- (void)setOneBallColor:(UIColor *)oneColor twoBallColor:(UIColor *)twoColor{
    self.oneLayer.fillColor = oneColor.CGColor;
    self.twoLayer.fillColor = twoColor.CGColor;
}

- (void)setAnimatorDuration:(CGFloat)duration{
    self.duration = duration;
}

- (void)setAnimatorDistance:(CGFloat)distance{
    self.distance = distance;
    if (distance > self.bounds.size.width*0.5) {
        self.distance = self.bounds.size.width*0.5;
    }
}

- (void)startAnimator{
    [self startOneBallAnimator];
    [self startTwoBallAnimator];
}

- (void)startOneBallAnimator{
    //第一个小球位移动画
    CAKeyframeAnimation *oneFrameAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
    CGMutablePathRef path = CGPathCreateMutable();
    CGPathMoveToPoint(path, NULL, self.centerPoint.x, self.centerPoint.y);
    CGPathAddLineToPoint(path, NULL, self.centerPoint.x+self.distance, self.centerPoint.y);
    CGPathAddLineToPoint(path, NULL, self.centerPoint.x, self.centerPoint.y);
    CGPathAddLineToPoint(path, NULL, self.centerPoint.x-self.distance, self.centerPoint.y);
    CGPathAddLineToPoint(path, NULL, self.centerPoint.x, self.centerPoint.y);
    [oneFrameAnimation setPath:path];

    //第一个小球缩放动画
    CABasicAnimation *oneScaleAnimation1 = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
    oneScaleAnimation1.fromValue = [NSNumber numberWithFloat:1.0];
    oneScaleAnimation1.toValue = [NSNumber numberWithFloat:0.5];
    oneScaleAnimation1.duration = self.duration*0.5;

    CABasicAnimation *oneScaleAnimation2 = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
    oneScaleAnimation2.fromValue = [NSNumber numberWithFloat:0.5];
    oneScaleAnimation2.toValue = [NSNumber numberWithFloat:1.0];
    oneScaleAnimation2.beginTime = self.duration*0.5;
    oneScaleAnimation2.duration = self.duration*0.5;

    //第一个小球透明动画
    CABasicAnimation *oneOpacityAnimation1 = [CABasicAnimation animationWithKeyPath:@"opacity"];
    oneOpacityAnimation1.fromValue = [NSNumber numberWithFloat:1.0];
    oneOpacityAnimation1.toValue = [NSNumber numberWithFloat:0.5];
    oneOpacityAnimation1.duration = self.duration*0.5;

    CABasicAnimation *oneOpacityAnimation2 = [CABasicAnimation animationWithKeyPath:@"opacity"];
    oneOpacityAnimation2.fromValue = [NSNumber numberWithFloat:0.5];
    oneOpacityAnimation2.toValue = [NSNumber numberWithFloat:1.0];
    oneOpacityAnimation2.beginTime = self.duration*0.5;
    oneOpacityAnimation2.duration = self.duration*0.5;

    CAAnimationGroup *oneScaleGroup = [CAAnimationGroup animation];
    [oneScaleGroup setAnimations:@[oneScaleAnimation1,oneScaleAnimation2,oneOpacityAnimation1,oneOpacityAnimation2]];

    //组合动画
    CAAnimationGroup *oneGroup = [CAAnimationGroup animation];
    [oneGroup setAnimations:@[oneFrameAnimation,oneScaleGroup]];
    oneGroup.duration = self.duration;
    oneGroup.repeatCount = HUGE;
    oneGroup.delegate = self;
    [self.oneLayer addAnimation:oneGroup forKey:@"oneGroup"];
}

- (void)startTwoBallAnimator{
    //第二个小球位移动画
    CAKeyframeAnimation *twoFrameAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
    CGMutablePathRef path = CGPathCreateMutable();
    CGPathMoveToPoint(path, NULL, self.centerPoint.x, self.centerPoint.y);
    CGPathAddLineToPoint(path, NULL, self.centerPoint.x-self.distance, self.centerPoint.y);
    CGPathAddLineToPoint(path, NULL, self.centerPoint.x, self.centerPoint.y);
    CGPathAddLineToPoint(path, NULL, self.centerPoint.x+self.distance, self.centerPoint.y);
    CGPathAddLineToPoint(path, NULL, self.centerPoint.x, self.centerPoint.y);
    [twoFrameAnimation setPath:path];

    //第二个小球缩放动画
    CABasicAnimation *twoScaleAnimation1 = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
    twoScaleAnimation1.fromValue = [NSNumber numberWithFloat:1.0];
    twoScaleAnimation1.toValue = [NSNumber numberWithFloat:2.0];
    twoScaleAnimation1.duration = self.duration*0.5;

    CABasicAnimation *twoScaleAnimation2 = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
    twoScaleAnimation2.fromValue = [NSNumber numberWithFloat:2.0];
    twoScaleAnimation2.toValue = [NSNumber numberWithFloat:1.0];
    twoScaleAnimation2.beginTime = self.duration*0.5;
    twoScaleAnimation2.duration = self.duration*0.5;

    //第二个小球透明动画
    CABasicAnimation *twoOpacityAnimation1 = [CABasicAnimation animationWithKeyPath:@"opacity"];
    twoOpacityAnimation1.fromValue = [NSNumber numberWithFloat:0.5];
    twoOpacityAnimation1.toValue = [NSNumber numberWithFloat:1.0];
    twoOpacityAnimation1.duration = self.duration*0.5;

    CABasicAnimation *twoOpacityAnimation2 = [CABasicAnimation animationWithKeyPath:@"opacity"];
    twoOpacityAnimation2.fromValue = [NSNumber numberWithFloat:1.0];
    twoOpacityAnimation2.toValue = [NSNumber numberWithFloat:0.5];
    twoOpacityAnimation2.beginTime = self.duration*0.5;
    twoOpacityAnimation2.duration = self.duration*0.5;

    CAAnimationGroup *oneScaleGroup = [CAAnimationGroup animation];
    [oneScaleGroup setAnimations:@[twoScaleAnimation1,twoScaleAnimation2,twoOpacityAnimation1,twoOpacityAnimation2]];

    //组合动画
    CAAnimationGroup *twoGroup = [CAAnimationGroup animation];
    [twoGroup setAnimations:@[twoFrameAnimation,oneScaleGroup]];
    twoGroup.duration = self.duration;
    twoGroup.repeatCount = HUGE;
    [self.twoLayer addAnimation:twoGroup forKey:@"twoGroup"];
}

- (void)stopAnimator{
    //TODO
}

- (void)animationDidStart:(CAAnimation *)anim{
    [self performSelector:@selector(startNSTimer) withObject:self afterDelay:self.duration*0.25];
}

- (void)startNSTimer{
    //添加定时器
    self.mTimer = [NSTimer scheduledTimerWithTimeInterval:self.duration*0.5 target:self selector:@selector(animationUpdateListener) userInfo:nil repeats:YES];

}

- (void)animationUpdateListener{
    if (self.isTwoAbove) {
        [self.layer insertSublayer:self.twoLayer below:self.oneLayer];
    }else{
        [self.layer insertSublayer:self.oneLayer below:self.twoLayer];
    }
    _isTwoAbove = !_isTwoAbove;
}

@end


五、怎样使用

像正常的UIView控件一样使用,目前只支持代码

TwoBallRotationProgressBar *progressBar1 = [[TwoBallRotationProgressBar alloc] initWithFrame:CGRectMake(0, 0, screen_width, screen_height/5)];
    [self.view addSubview:progressBar1];

    [progressBar1 setOneBallColor:[UIColor blueColor] twoBallColor:[UIColor blackColor]];
    //设置俩小球最大半径6
    [progressBar1 setBallMaxRadius:6];
    //设置俩小球最小半径3
    [progressBar1 setBallMinRadius:3];
    //设置动画时间1.5秒
    [progressBar1 setAnimatorDuration:1.5];

    [progressBar1 startAnimator];


六、源代码下载地址

以后所有涉及到的代码都会放到我的github仓库上面,有需要的可以去下载,github下载地址

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-09-30 20:44:57

IOS版本-两个小球不停的绕中心旋转的进度条的相关文章

Android-两个小球不停的绕中心旋转的进度条

转载请标明出处: http://blog.csdn.net/hanhailong726188/article/details/47363911 本文出自:海龙的博客 一.概述 最近做了一个比较清新的进度条,没啥难度的,就是涉及到属性动画和canvas绘制圆形的知识,因为群里有一个问怎么实现的,这里就稍微写了一下原理,先看效果图 二.效果图 Gif录制的帧数有点低,导致稍微有点卡,但是在真实运行的时候一点都不卡 三.实现原理 自定义view 自定义属性动画 canvas画圆 四.代码实现 因为代码

Qt QGraphicsItem 绕中心旋转、放缩

最近用到了QGraphicsItem,可以通过QGraphicsItemAnimation使其产生动画效果. QGraphicsItemAnimation自带了setPosAt().setRotationAt().setScaleAt()等方法可以用来移动.旋转.放缩QGraphicsItem,但其默认的OriginPoint是这个Item的左上角,虽然QGraphicsItem自带了setTransformOriginPoint()方法,但是设置以后没有效果,还是绕左上角放缩旋转,只好采取其他

IOS 计算两个经纬度之间的距离

一 丶 -(double)distanceBetweenOrderBy:(double) lat1 :(double) lat2 :(double) lng1 :(double) lng2{ CLLocation *curLocation = [[CLLocation alloc] initWithLatitude:lat1 longitude:lng1]; CLLocation *otherLocation = [[CLLocation alloc] initWithLatitude:lat2

iOS之UI--彩虹动画进度条学习和自主封装改进

前言: 首先展示一下这个iOS小示例的彩色进度条动画效果: 阅读本文先说说好处:对于基础不好的读者,可以直接阅读文末尾的"如何使用彩虹动画进度条"章节,然后将我封装好的这个功能模块类用到你的工程项目中即可. 这个效果的示例是老外Nick Jensen在2013年写的一个作品:使用CAGradientLayer的动画精度条View. 本人阅读了老外的源码之后,觉得老外这个进度条的效果很不错,但是觉得他写的代码有待改进. 小贴士:读者可以直接将老外的源码下载下来,跑一下,然后对比本人写的博

实现Canvas2D绘图 使元素绕中心居中旋转

我之前用canvas写了个头像剪切的demo,但是关于让载入的图片旋转是个问题,虽然通过其它方法实现了,但是感觉并不太好,于是查了些资料,想试着重新做一下canvas的旋转. 在开始之前,先让我们来做一些准备工作: 1 (function () { 2 // 设置画布的宽高 3 var width = 300, 4 heigh = 100, 5 cache = {}; // 存储canvas上下文 6 7 // 获取绘图上下文 8 function getCtx(name, w, h) { 9

Unity3D 实现简单的语音聊天 [iOS版本]

现在很多手机游戏中的聊天系统都加入语音聊天的功能,相比于传统的文字聊天,语音聊天在MMORPG中显得尤为重要,毕竟直接口头交流总比你码字快得多了,也更直观些. 实现语音聊天的方法很多,U3D中有不少第三方的插件,提供了很多功能强大的语音功能,具体有哪些我就不一一举例了(其实我都没用过- -!),本文想从一个原生开发的角度去实现一个简单的语音聊天功能. 语音聊天大概流程如图: 上图中可以看到,客户端录制语音数据,并进行编码转换,数据压缩,然后把语音数据发送到语音服务器,语音服务器进行派发功能(语音

IOS版本被拒的经历

IOS版本被拒的经历: 1,登陆方式依赖外部平台 因为我们的APP是只用微博登陆,想做成类似meerkat类型的,也能各种消息都同步微博. 结果当然行不通,这个确实是不听好人言,网上多个人都说过这个问题了,早就该引以为戒! 后加入手机号登陆,问题搞定. 2,放在app store中的广告图片有手机画面中,状态栏是android的 这个我们太不小心了,后修改图片. 3,用户排行榜中,列举所有用户,并且在UITableViewCell中例举了用户名.头像.粉丝数.关注数.人气量,苹果认为粉丝数.关注

银行卡卡号识别:C#版本和iOS版本

(一)图像采集 首先我们要取得待识别的图像.这项工作可以通过数码相机.DV机.工业摄像机.电脑数字摄像头.手机摄像头等设备采集,并从中取得我们要分析的图像信息. (二)版面分析 取得图像信息后,要对图像整体版面进行分析.这一步工作如果使用通用算法进行分析,则效率很低.通常情况下都需要针对不同的识别对象进行专门的分析及设定,才能取得良好的分析效果. 抠出数字???? 倾斜图像校正?? http://www.doc88.com/p-34555054276.html (三)图像灰度化 从采集设备里取得

IOS中两个view的切换

在ios中,rootview为PassWordViewController,secondview为SecondViewController,实现在rootview中听过一个跳转按钮实现跳转到secondview中,实现方法如下: 在PassWordViewController.h中添加button的事件 -(IBAction) landButtonPressed:(id) sender; 在PassWordViewController.m中 button的实现事件如下: -(IBAction)