环形进度条的简单实现
来源:互联网 发布:淘宝专业术语大全 编辑:程序博客网 时间:2024/06/01 10:23
小牢骚
好久没有记录文章了,近期在学习前端的相关知识,也没有好好的静下心来整理东西,这次准备把之前自己用到的东西做一个总结,方便以后自己查阅.
正文
这次记录使用CALayer创建一个环形进度条的view,加上简单的动画,项目中刚好有使用到。
效果图:
要点: 主要使用layer的mask属性,mask属性可以让layer只显示遮罩层上面的路径(环形)
分析
在进度值为0的时候,有一个黄色的底色,然后进度条的颜色是渐变的,底色环形可以通过给view的layer添加一个带环形路径的CAShapeLayer作为mask,渐变色可以使用CAGrandientLayer创建一个渐变图层,然后创建一个带环形路径的CAShapeLayer,将其作为渐变图层的mask,这样就能达到预期的效果
相关知识点
- CAGradientLayer
创建渐变色layer,他是继承自CALayer的一个用于绘制多色图层的子类,主要用于设置的属性值为- @property(nullable, copy) NSArray *colors;
设置需要加载的颜色数组(CGColorRef类型) - @property(nullable, copy) NSArray
- @property(nullable, copy) NSArray *colors;
#define DEGREES_TO_ANGLE(x) (M_PI * (x) / 180.0) // 将角度转为弧度CAShapeLayer *layer = [CAShapeLayer layer]; layer.frame = self.bounds; UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(self.bounds.size.width / 2, self.bounds.size.height / 2) radius:self.bounds.size.width / 2.5 startAngle:DEGREES_TO_ANGLE(-90) endAngle:DEGREES_TO_ANGLE(270) clockwise:YES]; //注意这里的半径,应该为宽度1/2-linewidth/2 layer.lineWidth = self.lineWidth; //线的宽度 layer.path = path.CGPath; layer.fillColor = [UIColor clearColor].CGColor; //设置填充颜色 layer.strokeColor = [UIColor blackColor].CGColor; // 设置画笔颜色 layer.lineCap = kCALineCapRound; // 设置线为圆角
其中需要注意的点:
- 这里的坐标系和数学中的坐标系是反的,简单的理解就是-90°等价数学坐标系中的90°,90°等价数学坐标系中的270°,所以如果希望进度条从顶部按照顺时针走,那么在设置UIBezierPath画圆弧的时候就应该为clockwise:yes(顺时针),startangle(开始弧度):(-90°对应的弧度),endangle:(270°对应的弧度),这样就是生成按照顺时针方向从-90°的点到270°的点之间的路径。
如下图片中不同的角度对应的效果图:
- 在选择半径时,如果fram宽度为100,希望绘制一个宽度20紧靠边缘的环形,那么半径应该是50-20/2,并不是50-20。
代码解析
progressView.h
typedef NS_ENUM (NSInteger, WJStrokeType)//动画方式{ WJStrokeTypeStart, //开始 WJStrokeTypeEnd //结束};//动画结束回调typedef void(^ProgressEnd)();@interface WJProgressView : UIView/** * 线宽 */@property(nonatomic,assign)CGFloat lineWidth;/** * 背景颜色 */@property(nonatomic,strong)UIColor *bgColor;/** * 渐变色颜色组 */@property(nonatomic,strong)NSArray *colors;/** * 颜色分割位置数组 */@property(nonatomic,strong)NSArray *locations;/** * 隐藏百分比label */- (void)hidePercent;/** * 设置创建图层 */- (void)startProress;/** * 更新progress * * @param value progress Value */- (void)reloadValue:(CGFloat)value;/** * 进度动画 * * @param beginValue 开始value * @param endValue 结束value * @param duration 动画持续时间 * @param type 动画类型 * @param endBlock 动画结束回调 */- (void)setprogressFromValue:(CGFloat)beginValue endValue:(CGFloat)endValue duration:(CGFloat)duration strokeType:(WJStrokeType)type end:(ProgressEnd)endBlock;
.m
- (void)setprogressFromValue:(CGFloat)beginValue endValue:(CGFloat)endValue duration:(CGFloat)time strokeType:(WJStrokeType)type end:(ProgressEnd)endBlock{ if (beginValue >= 1.0) { endBlock(); return; } _endValue = endValue; self.animationEnd = endBlock; NSString *animationName = @"strokeStart"; if (type) { animationName = @"strokeEnd"; } CABasicAnimation *pathAnimation = [CABasicAnimation animationWithKeyPath:animationName]; pathAnimation.duration = time; pathAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear]; pathAnimation.fromValue = [NSNumber numberWithFloat:beginValue]; pathAnimation.toValue = [NSNumber numberWithFloat:endValue]; pathAnimation.autoreverses = NO; pathAnimation.delegate = self; pathAnimation.removedOnCompletion = NO; pathAnimation.fillMode = kCAFillModeForwards; [self.colorMaskLayer addAnimation:pathAnimation forKey:@"strokeAnimation"]; [self creatTimerFromValue:beginValue endValue:endValue duration:time];}
对于cCAShapeLayer,stokeEnd和strokestart属性都直接动画操作。
在动画过程中关于中间percentLabel的显示,使用定时器设置时间间隔实现变化。
/** 创建定时器在layer animation过程中改变percent @param beginValue 初始值 @param endValue 结束值 @param time 时间间隔 */- (void)creatTimerFromValue:(CGFloat)beginValue endValue:(CGFloat)endValue duration:(CGFloat)time{ __block CGFloat beginPercent = beginValue; CGFloat timeInterval = 0.1; dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); self.timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue); dispatch_source_set_timer(self.timer, dispatch_walltime(NULL, 0), timeInterval*NSEC_PER_SEC, 0); dispatch_source_set_event_handler(self.timer, ^{ dispatch_async(dispatch_get_main_queue(), ^{ CGFloat difference = endValue - beginValue; CGFloat addValue = difference/time/(1/timeInterval); beginPercent += addValue; if (beginPercent >= endValue) beginPercent = endValue; if (beginPercent >= 1.0) beginPercent = 1.0f; [self reloadPercentLabelValue:beginPercent]; }); }); dispatch_resume(_timer);}
注意点:dispatch_source_t 的创建定一个属性值来保存。不要直接在方法中创建。
在动画结束后对timer进行销毁处理。
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag{ if (self.animationEnd) self.animationEnd(); [self.colorMaskLayer removeAnimationForKey:@"strokeAnimation"]; self.colorMaskLayer.strokeEnd = _endValue; if (self.timer) { dispatch_source_cancel(self.timer); self.timer = nil; }}
End demo地址
- 环形进度条的简单实现
- 环形进度条的简单实现
- 环形进度条的实现
- SVG环形进度条的实现方法
- 带波形进度的环形进度条实现
- android实现环形进度条
- canvas实现环形进度条
- canvas 实现环形进度条
- UGUI实现环形进度条
- MFC环形进度条实现
- 环形进度条的制作
- android 简单自定义环形进度条
- jQuery+CSS实现环形进度条
- 如何实现一个环形进度条
- 自定义Drawable实现环形进度条.
- 进度条的简单实现
- 进度条的简单实现
- 简单进度条的实现
- Java内存分配
- DOS/DDOS攻击的iptables测试,日志查看
- 织梦dedecms模板中运行php代码和mysql语句总结
- hdu6171 双向bfs
- 1040:计算1~N之间所有的奇数之和
- 环形进度条的简单实现
- 观察者模式——猫和老鼠(什么原来这里是标题吗)
- JAVAEE之Spring学习(五)---SpringMVC注解实现功能的详解
- Codeforces 812B-Sagheer, the Hausmeister
- 子网掩码255.255.0.0与255.255.255.0的区别
- Java开发工具包下载安装和配置
- MPC8309 USB OTG功能调试
- jquery遍历json的方法
- ios 适配