一、概述
昨天實現了一個Android版本的小清新動畫,可以當成進度條來用,這裡補上IOS版本的
二、效果圖
三、實現原理
自定義UIView,然後添加兩個CALayer,通過CAShapeLayer和UIBezierPath畫出兩個小圓球,動起來是通過CAAnimation動畫,動畫包括小球的位移動畫、縮放動畫、透明動畫組合起來的,因為涉及的東西不是很難,下面就直接貼代碼了
四、代碼實餡喎?/kf/yidong/wp/" target="_blank" class="keylink">WPC9zdHJvbmc+PC9wPg0KVHdvQmFsbFJvdGF0aW9uUHJvZ3Jlc3NCYXIuaA0KPHByZSBjbGFzcz0="brush:java;">
2 . TwoBallRotationProgressBar.m 五、怎樣使用 //
// TwoBallRotationProgressBar.h
// TwoBallRotationProgressBar
//
// Created by HailongHan on 15/8/8.
// Copyright (c) 2015年 hhl. All rights reserved.
//
#import
//
// 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];