效果如图:
根据项目需求,实现了以上效果的圆环;
对于圆环,主要分三层:
1.最底层灰色圆环;
2.上层的进度圆环;
3.进度小圆点;
里面的内容显示用Masonry进行布局即可,这里就不过多介绍;
圆环的实现使用CAShapeLayer,通过UIBezierPath绘制圆环路径,并将该路径赋值给CAShapeLayer的path属性;
CAShapeLayer的常用属性:
path //从贝塞尔曲线获取到形状
strokeColor //边缘线的颜色
fillColor //闭环填充的颜色
lineCap //边缘线的类型
lineWidth //线条宽度
strokeStart //画笔起始位置
strokeEnd //画笔结束位置
底层圆环绘制代码:
- (void)drawDownLayer
{
if(!_downLayer){
_downLayer = [[CAShapeLayer alloc]init];
_downLayer.frame = self.bounds;
UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:CGPointMake((CGRectGetMaxX(self.frame) - CGRectGetMinX(self.frame)) / 2, (CGRectGetMaxY(self.frame) - CGRectGetMinY(self.frame)) / 2) radius:self.bounds.size.width/2 startAngle:(M_PI*(-90))/180 endAngle:(M_PI*(270))/180 clockwise:YES];
_downLayer.path = path.CGPath;
_downLayer.lineWidth = self.linewidth;
_downLayer.lineCap = kCALineCapSquare;
_downLayer.strokeColor = [UIColor lightGrayColor].CGColor;
_downLayer.fillColor = [UIColor clearColor].CGColor;
[self.layer addSublayer:_downLayer];
}
}
上层的进度圆环绘制代码:
- (void)drawUpLayer
{
if(!_upLayer){
_upLayer = [[CAShapeLayer alloc]init];
CABasicAnimation *pathAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
pathAnimation.duration = self.duration;
pathAnimation.fromValue = [NSNumber numberWithFloat:0.0f];
pathAnimation.toValue = [NSNumber numberWithFloat:1.0f];
[_upLayer addAnimation:pathAnimation forKey:@"shapeLayerAnimation"];
_upLayer.frame = self.bounds;
UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:CGPointMake((CGRectGetMaxX(self.frame) - CGRectGetMinX(self.frame)) / 2, (CGRectGetMaxY(self.frame) - CGRectGetMinY(self.frame)) / 2) radius:self.bounds.size.width/2 startAngle:(M_PI*(-90))/180 endAngle:(M_PI*(270))/180*_percent clockwise:YES];
path.lineCapStyle = kCGLineCapRound;
_upLayer.path = path.CGPath;
_upLayer.lineWidth = self.linewidth;
_upLayer.lineCap = kCALineCapRound;
_upLayer.strokeColor = self.color.CGColor;
_upLayer.fillColor = [UIColor clearColor].CGColor;
[_downLayer addSublayer:_upLayer];
}
}
由于上层圆环的动画时间有一定要求,所以使用CABasicAnimation对其动画时间进行操作
两层圆环的绘制已经完成,接下来是小圆点的路径和运动;
使用CAKeyframeAnimation,并为其添加圆形运动轨迹:
- (void)point
{
CAKeyframeAnimation *pathAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
pathAnimation.calculationMode = kCAAnimationPaced;
pathAnimation.fillMode = kCAFillModeForwards;
pathAnimation.removedOnCompletion = NO;
pathAnimation.duration = self.duration;
pathAnimation.repeatCount = 0;
float radiuscale = 1;
CGFloat origin_x = self.frame.size.width/2;
CGFloat origin_y = self.frame.size.height/2;
CGFloat radiusX = self.frame.size.width/2;
float a = -M_PI / 2;
float b = (-M_PI / 2 + 2 * M_PI) * _percent;
CGMutablePathRef path = CGPathCreateMutable();
CGAffineTransform t = CGAffineTransformConcat(CGAffineTransformConcat(CGAffineTransformMakeTranslation(-origin_x, -origin_y),CGAffineTransformMakeScale(radiuscale, radiuscale)),
CGAffineTransformMakeTranslation(origin_x, origin_y));
CGPathAddArc(path, &t, origin_x, origin_y, radiusX ,a , b, 0);
pathAnimation.path = path;
CGPathRelease(path);
if(!_point){
_point = [[UIView alloc] init];
[self addSubview: _point];
_point.frame = CGRectMake(self.bounds.size.width/2, 0, self.linewidth*2+2, self.linewidth*2+2);
[_point.layer setCornerRadius:(self.linewidth*2+2)/2];
_point.backgroundColor = self.color;
[_point.layer addAnimation:pathAnimation forKey:@"movePoint"];
}
}