CRNetworkButton源码深度解析:Core Animation实现旋转加载动画的底层原理
CRNetworkButton源码深度解析Core Animation实现旋转加载动画的底层原理【免费下载链接】CRNetworkButtonSend Button for iOS项目地址: https://gitcode.com/gh_mirrors/cr/CRNetworkButton点击发送按钮后它迅速收缩成圆形、亮起一圈旋转的加载动画请求完成后弹出对勾或叉号——这段行云流水的交互反馈来自开源 iOS 组件CRNetworkButton。这是一个专为网络请求场景设计的 iOS 网络按钮把整套加载动画内嵌进控件本身而且全部实现仅用一个 Swift 文件CRNetworkButton.swift约 850 行完成。本文将深入源码剖析它如何用 Core Animation 的CABasicAnimation、CAAnimationGroup与CAShapeLayer拼出旋转加载动画并拆解其底层原理帮你彻底读懂这套 iOS 动画的最佳实践。CRNetworkButton 是什么自带加载动画的 iOS 网络按钮CRNetworkButton 由 Cleveroad 团队开源本质是UIButton的子类专为点击按钮 → 发起网络请求 → 展示加载进度 → 反馈成功/失败这一完整交互闭环而设计。它把加载状态直接内嵌进按钮加载时按钮变成圆形并持续旋转成功时变为对勾失败时变为叉号用户全程无需离开按钮即可获知请求状态。如上图所示三个按钮分别演示了普通模式、进度模式与错误模式。整段动画完全由 Core Animation 驱动运行在渲染服务端CPU/GPU 开销极低即使连续点击也不会卡顿。读懂四状态机动画流转的总开关源码第一段就定义了一个枚举 CRState这是理解全部动画代码的钥匙public enum CRState { case ready // 就绪显示初始文字 case loading // 加载中显示旋转动画 case finishing // 收尾中旋转归位、圆点放大、对勾回弹 case finished // 完成显示 Done / Error }状态切换通过crState的didSet触发handleCRState分发到对应动画方法整个动画流程就是在这四个状态间有序流转。对外暴露的startAnimate()、stopAnimate()、stopByError()其实都只是在改状态真正的动画逻辑由状态机统一调度。旋转加载动画的底层原理弧线段 无限旋转旋转动画的核心在 startLoadingAnimation 方法它分两步完成第一步用 CAShapeLayer 绘制弧线段先按linesCount数量创建若干条弧线每条弧线都是一个CAShapeLayer路径用UIBezierPath的 arc 方法绘制均匀分布在圆周上相邻夹角 2π / linesCount弧长由dotLength弧度制控制let lineOffset 2 * CGFloat(M_PI) / CGFloat(linesCount) for i in 0..linesCount { let line CAShapeLayer() line.path UIBezierPath(arcCenter: arCenter, radius: radius, startAngle: lineOffset * CGFloat(i), endAngle: lineOffset * CGFloat(i) dotLength, clockwise: true).cgPath // 设置描边色、线宽、圆头线帽 }第二步transform.rotation.z 无限旋转这是整段旋转加载动画的灵魂。对每条弧线图层施加一个围绕 Z 轴的旋转动画let rotation CABasicAnimation(keyPath: transform.rotation.z) rotation.byValue NSNumber(value: 2 * M_PI) // 每次旋转一整圈 rotation.duration velocity // 转一圈耗时 velocity 秒 rotation.repeatCount Float.infinity // 无限循环底层原理拆解keyPath 的选择transform.rotation.z属于 transform 动画直接在渲染服务端完成矩阵运算不触发布局与重绘性能远优于逐帧修改 framebyValue 增量动画相对当前值累加 2π即每次转满 360°配合repeatCount .infinity实现永不停歇的旋转velocity 控制速度转一圈的秒数恰好等于velocity属性改一个数值即可调节旋转快慢这也是 Demo 里调节加载节奏的入口。矩形按钮如何变成圆形CAAnimationGroup 组合动画加载之前按钮要先从矩形缩成圆形这个过渡在 prepareLoadingAnimation 中完成涉及两组并行动画按钮图层bounds矩形→圆形backgroundColor→白色组合成一个CAAnimationGroup边框图层borderWidthboundsposition三合一让边框同步收缩并居中。这里有个关键细节fillMode kCAFillModeForwards且isRemovedOnCompletion false保证动画结束后图层停留在最终状态而不是弹回原点。另外两组合成动画都必须等全部结束才进入旋转环节这正是后面要讲的 DispatchGroup 协调机制的用武之地。结束动画三部曲旋转归位、圆点放大、对勾回弹停止加载后按钮并不会直接变回原样而是上演一气呵成的三部曲分别对应 finishAnimation、dotsScalingAnimation、checkMarkAndBoundsAnimation 三个方法旋转归位读取每条弧线图层的presentation()呈现层当前 transform 作为fromValue动画回CATransform3DIdentity实现从旋转中的任意角度平滑停下——这是很多开发者容易忽略的高级技巧圆点放大把弧线替换成小圆点做transform.scale放大动画视觉上线变点对勾与回弹对勾或叉号用CAKeyframeAnimation控制 opacity 闪现边框bounds以关键帧 [圆形 → 1.2 倍 → 原尺寸] 模拟弹性回弹按钮重新展开成矩形并显示 Done/Error 文字。进度模式strokeEnd 驱动的进度环把progressMode设为 true 后按钮进入进度模式一个CAShapeLayer圆环progressLayer被插入图层树updateProgress 通过修改strokeEnd0~1实时绘制进度。业务方只需配合定时器就能做出平滑的下载进度环示例见 ViewController.swift。多动画协调机制DispatchGroup CAAnimationDelegate一组动画往往包含多个图层并行执行如何等它们全部结束再继续下一步源码的做法非常巧妙每个动画通过 assignContext 打上自定义标识kAnimationIdentifierLoadingStart / Loading / LoadingFinishing添加动画前调用prepareGroup.enter()动画结束回调 animationDidStop 中对应leave()用DispatchGroup.notify在全部动画结束后于主队列执行下一步。这样就把一组并行 Core Animation封装成可编排的串行流程代码读起来非常清爽也是本库最值得学习的工程技巧之一。快速上手CocoaPods 集成与状态 API接入非常简单克隆仓库地址 https://gitcode.com/gh_mirrors/cr/CRNetworkButton后进入 Example 目录执行pod install即可运行示例或者直接在 Podfile 中添加一行pod CRNetworkButton然后在 Storyboard 中拖入控件得益于IBDesignable可实时预览代码里只需四个核心调用button.startAnimate() // 开始加载旋转动画 button.stopAnimate() // 成功结束并显示对勾 button.stopByError() // 失败结束并显示叉号 button.updateProgress(p) // 进度模式更新进度完整调用示例见 ViewController.swift 与模拟网络请求的 FakeNetworkManager.swift工程配置可参考 CRNetworkButton.podspec。可配置项一览从速度到线条数量的全部参数得益于IBInspectable绝大多数参数可直接在 Storyboard 右侧面板配置无需写代码属性作用velocity旋转一圈耗时秒控制加载速度linesCount旋转弧线段数量dotLength弧线段长度弧度制crDotColor / crErrorColor加载色 / 错误色crLineWidth线条宽度progressMode是否启用进度模式shouldAutoReverse结束后是否自动回到初始状态animateOnTap点击是否自动触发动画总结CRNetworkButton 用不到一千行代码展示了 Core Animation 在交互控件上的完整实践状态机驱动流程、CAShapeLayer 绘制弧线与对勾、transform.rotation.z实现高性能无限旋转、CAAnimationGroup 编排组合动画、DispatchGroup 协调多动画时序。对想深入 Core Animation 的 iOS 开发者而言这份源码是绝佳的学习样本——读懂它旋转加载动画的底层原理也就尽在掌握未来设计自己的加载组件也会事半功倍。【免费下载链接】CRNetworkButtonSend Button for iOS项目地址: https://gitcode.com/gh_mirrors/cr/CRNetworkButton创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

最新新闻

日新闻

周新闻

月新闻