画个Shape留意到的东西
这几个知识点
在 CoreGraphics 框架中有这样一个方法:
1 | public func addArc ( center : CGPoint , radius : CGFloat , startAngle : CGFloat , endAngle : CGFloat , clockwise : Bool ) |
这个方法是用来画圆的,这个方法就引出第一个知识点 startAngle 和 endAngle ,按照通俗的方法就是画的圆的起点的角度和结束点的角度。也就是我们的 0 - 2π ,最后一个参数是 是否顺时针。
按照我们学习到的知识,这圆周上任何一个圆角度 + 2π和原本的圆角度的值是一样的,比如下面的0和2π都是一个角度值的。这点东西在下面我们画进度的时候会用到的。
1 2 3 4 | /* Set the line cap in the current graphics state to `cap'. */ @ available ( iOS 2.0 , *) public func setLineCap ( _ cap : CGLineCap ) |
这个CGLineCap 我们在下面也有使用到,都已同样的含义,只是定义稍微有点不同,针对这个点 在这篇文章中有说清楚的
还有一点需要我们留意的,就是抗锯齿的效果,具体的这篇文章留意
CALayer 都加应该都知道,我们用到的是它的子类 CAShapeLayer,还有一个 CADisplayLink ,关于 CADisplayLink 和NSTime的比较我以前有说过,这里就不再重复写了,有兴趣的可以翻一下以前的文章,或者搜一下他们两者之间的区别。
最后我们就需要 UIBezierPath 帮我们指定一下画圆的路径。
效果是这样的
看看代码
第一步:画这个进度的底色圆
1 2 3 4 5 6 7 8 9 10 11 12 | func drawBaseProcess () - > Void { let path : UIBezierPath = UIBezierPath ( arcCenter : CGPoint ( x : kScreenWidth / 2 , y : 200 ), radius : 100 , startAngle : 0 , endAngle : CGFloat ( 2 * Double . pi ), clockwise : true ) let shadowLayer = CAShapeLayer () shadowLayer . fillColor = UIColor . clear . cgColor shadowLayer . strokeColor = UIColor . green . cgColor shadowLayer . frame = self . bounds ; // 边框的宽度 shadowLayer . lineWidth = backgroundLineWidth shadowLayer . path = path . cgPath self . layer . addSublayer ( shadowLayer ) } |
第二步:绘制这个显示进度的圆
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | func drawProcessing () - > Void { circleLayer = CAShapeLayer () circleLayer . fillColor = UIColor . clear . cgColor circleLayer . strokeColor = UIColor ( red : 64 / 255.0 , green : 10 / 255.0 , blue : 107 / 255.0 , alpha : 1.0 ). cgColor /// 这个是设置线的头部是圆角 circleLayer . lineCap = CAShapeLayerLineCap . round circleLayer . frame = self . bounds circleLayer . lineWidth = progressLineWidth self . layer . addSublayer ( circleLayer ); /// lineBreakMode属性介绍 https://www.jianshu.com/p/9dfc06b4bed9 progressLabel . lineBreakMode = NSLineBreakMode . byTruncatingTail /// 进度记录 self . progressLabel . text = String ( format : "%.2f" , self . progress ); /// let endangle : CGFloat = CGFloat ( 1.5 * Double . pi ) + self . progress * pi2 /// 计时器停止 if self . progress > = 1 { displayLink ?. invalidate () } /// let bezierPath = UIBezierPath ( arcCenter : CGPoint ( x : kScreenWidth / 2 , y : 200 ), radius : 100 , startAngle : CGFloat ( 1.5 * Double . pi ), endAngle : endangle , clockwise : true ) self . circleLayer . path = bezierPath . cgPath ; } |
第三步:我们需要一个计时器帮助我们实现这个进度(当然在实际的项目中有你自己的控制需求)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | override init ( frame : CGRect ) { super . init ( frame : frame ) ///self.backgroundColor = UIColor.init(red: 0, green: 0, blue: 0, alpha: 0.6) self . backgroundColor = . white /// self . addSubview ( progressLabel ) /// 画进度条的底圈 drawBaseProcess () /// 定时器 displayLink = CADisplayLink . init ( target : self , selector : # selector ( processing )) displayLink ?. add ( to : RunLoop . main , forMode : . default ) displayLink ?. preferredFramesPerSecond = 1 } /// 定时器执行方法 @objc func processing () { progress += 0.05 } |
## 努力做一个合格的程序员。
分类:
iOS 动画笔记
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话