利用CALayer动画实现渐变进度条

王朝学院·作者佚名  2016-08-27
窄屏简体版  字體: 小  |  中  |  大  |  超大  

今天是第一次写博客,希望在今后的日子里大家可以共同进步提高。闲话不多说了,首先看一下效果图。

其实这个空间是比较简单的调用CALayer动画的空间,首先我们做一下简单的分析。这个动画的组成分为两部分,第一部分为填充部分,即“strokeEnd”,另一部分则是填充颜色,即“stroke color”。有这两个动画组成了一个CALayer的组动画。

实现原理大致明确我们来用代码实现一下,我们先修改一下它的初始化方法:

-(instancetype)initWithFrameAndPRosse:(CGRect)frame prosseInfo:(ProssenInfo)prosseInfo

{

self = [super initWithFrame:frame];

if(self)

{

_prossenInfo = prosseInfo;

[self setCAShapeLayer];

}

return self;

}

这里面我将所需的一部分关于CAShapeLayer的参数写成了一个结构体,方便使用和查找,接下来我们初始化一下CAShapeLayer这个属性:

-(void)setCAShapeLayer

{

_prosseShape = [CAShapeLayer layer];

_prosseShape.strokeColor = _prossenInfo.lineColor;

_prosseShape.lineWidth = _prossenInfo.width;

_prosseShape.strokeStart = 0;

_prosseShape.strokeEnd = 0;

_prosseShape.path = [self prossePath];

_prosseShape.lineJoin = kCALineJoinRound;

_prosseShape.lineCap = kCALineCapRound;

_prosseShape.beginTime =0.1f;

[self.layer addSublayer:_prosseShape];

}这里我们需要注意

_prosseShape.lineJoin = kCALineJoinRound;

_prosseShape.lineCap = kCALineCapRound;这两句话,如果不加上的话实现出来的进度条就不是圆角的。

我们改如何给路径呢?

-(AnimationPoint)animationPoint

{

CGFloat startPoint_x = self.frame.size.width*(_prossenInfo.minLength<_prossenInfo.maxLength?_prossenInfo.minLength:_prossenInfo.maxLength);

CGFloat endPoint_x = self.frame.size.width*(_prossenInfo.minLength>_prossenInfo.maxLength?_prossenInfo.minLength:_prossenInfo.maxLength);

AnimationPoint point = AnimationPointMake\

(CGPointMake(startPoint_x, self.frame.size.height/2.f-_prossenInfo.width/2.f), \

CGPointMake(endPoint_x, self.frame.size.height/2.f-_prossenInfo.width/2.f));

return point;

}

-(CGMutablePathRef)prossePath

{

AnimationPoint point = [self animationPoint];

CGMutablePathRef pathRef=CGPathCreateMutable();

CGPathMoveToPoint(pathRef, NULL,point.startPoint.x, point.startPoint.y);

CGPathAddLineToPoint(pathRef, NULL, point.endPoint.x,point.endPoint.y);

CGPathCloseSubpath(pathRef);

return pathRef;

}

我们给定了这个Layer的起始填充部分,颜色,宽度以及路径,接下来我们开始着手关于它的动画。

-(void)starAnimation:(NSArray *)colorArray time:(NSTimeInterval)time

{

__block BOOL colors = NO;

__weak CAShapeLayer *shape = _prosseShape;

__block NSMutableArray *animationArray = [NSMutableArray array];

_aniTime = time;

[shape animateKey:@"strokeEnd"

fromValue:[NSNumber numberWithFloat:0.f]

toValue:[NSNumber numberWithFloat:0.5f]

customize:^BOOL(CABasicAnimation *animation) {

animation.duration = time;

if (colorArray != nil) {

colors = YES;

[animationArray addObject:animation];

[shape keyAnimation:@"strokeColor"

keyValues:colorArray

customize:^BOOL(CAKeyframeAnimation *animation) {

animation.duration = time;

animation.calculationMode = kCAAnimationPaced;

[animationArray addObject:animation];

return colors;

}];

[shape animationGroupWithDuration:time

animations:animationArray

customize:^(CAAnimationGroup *animation) {

}];

}

else

{

colors = NO;

animation.delegate = self;

}

return colors;

}];

}

因为我们要实现的事渐变颜色的动画效果,所以我们需要给定两个参数,一个是颜色数组,一个是进度时间。(当然在实际的下载过程中我们是不知道进度时间的,所以这里本人封装的控件还不具备很好的完整性,但是我们可以通过修改 toValue:[NSNumber numberWithFloat:0.5f]这个函数参数来实现下载进度,本人会在下篇博客之前修改完毕)。接下来我们实现一下关于动画时间的计算,因为CALayer动画本来是不支持动画时间监听的,所以这里面我用了一个定时器。

-(void)animationDidStart:(CAAnimation *)anim

{

_animationTimer = [NSTimer scheduledTimerWithTimeInterval:AnimationTimer target:self selector:@selector(progressDidStart:) userInfo:nil repeats:YES];

}

-(void)progressDidStart:(NSTimer *)timer

{

if (_delegate &&[_delegate respondsToSelector:@selector(prosseToPoint:withDot:)]) {

animationProgress += 1/(_aniTime/AnimationTimer);

if (animationProgress >= 1.0) {

animationProgress = 1.0;

}

[_delegate prosseToPoint:CGPointZero withDot:animationProgress];

}

}

-(void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag

{

if (_delegate &&[_delegate respondsToSelector:@selector(prosseToPoint:withDot:)]) {

animationProgress += 1/(_aniTime/AnimationTimer);

if (animationProgress >= 1.0) {

animationProgress = 1.0;

}

[_delegate prosseToPoint:CGPointZero withDot:animationProgress];

}

animationProgress = 0;

[_animationTimer invalidate];

_animationTimer = nil;

}

这样我们一个简单的进度条控件就写好了,下面我们来调用一下:

_proView = [[XDProsseView alloc]initWithFrameAndProsse:CGRectMake(10, 320, self.view.bounds.size.width-20, 50) prosseInfo:ProssenInfoMake(5,1.f , 0.0, [UIColor blueColor].CGColor)];

_proView.delegate = self;

[self.view addSubview:_proView];

初始化这个进度条,

[_proView starAnimation:[NSArray arrayWithObjects:(id)[UIColor greenColor].CGColor,(id)[UIColor redColor].CGColor,(id)[UIColor blackColor].CGColor, nil] time:10.234f];

设置开始,时间,颜色等。

-(void)prosseToPoint:(CGPoint)point withDot:(double)dot

{

NSLog(@"监听进度条进度%@ %ld",NSStringFromCGPoint(point),dot);

}

第一次写博客,如果有什么不妥的地方,希望大家及时提出来,我一定会积极改正,谢谢!

 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
 
© 2005- 王朝網路 版權所有 導航