ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

为什么圆环图这么顺滑?EChart的EPieChart三层CAShapeLayer弧绘制原理剖析

2026/8/23 12:32:00 拓冰建站 浏览量
为什么圆环图这么顺滑?EChart的EPieChart三层CAShapeLayer弧绘制原理剖析 为什么圆环图这么顺滑EChart的EPieChart三层CAShapeLayer弧绘制原理剖析【免费下载链接】EChartiOS/iPhone/iPad Chart, Graph. Event handling and animation supported.项目地址: https://gitcode.com/gh_mirrors/ec/EChartEChart 是一款面向 iOSiPhone/iPad的轻量级开源图表库支持事件处理与动画。其中的 EPieChart 圆环图以动画丝滑著称。这篇文章从源码层面剖析它的绘制原理三层 CAShapeLayer 各自负责哪段弧以及strokeEnd动画如何让圆环图以 60 帧的顺滑度画出来。圆环图上有什么预算、当前、预估三个数字先看效果。演示页面 EPieChartViewController.m 创建了一个 150×150 的圆环图传入的数据模型如下数据含义演示值budget预算总量133current当前进度33estimate预估进度77数据由 EPieChartDataModel 承载环心还会显示 B / C / E 三行滚动数字。视觉上则是白色细底环 一段半透明黄色弧 一段实心黄色弧全部从 12 点钟方向顺时针展开。三层 CAShapeLayer 弧分层各司其职整个圆环图的核心绘制集中在 EPieChart.m 的reloadContent方法里。每个圆环EPie视图内部只有三个 CAShapeLayer它们同心、同半径radius × 0.8、同线宽radius / 6仅靠路径角度和zPosition区分层级图层变量路径zPosition作用底层_circleBudget0° → 360° 完整圆环-1白色满量程背景轨道中层_circleEstimate270° → 270° − 77/133×360°0半透明黄30% 不透明度表示预估顶层_circleCurrent270° → 270° − 33/133×360°1实心黄表示当前进度几个值得注意的细节三层fillColor都是透明色颜色全部来自strokeColor——即只描边、不填充所以是环而不是饼lineCap kCALineCapRound让弧线两端呈圆角视觉更柔和zPosition-1 / 0 / 1决定叠加顺序当前进度永远盖在预估弧之上底环垫底一眼就能分出目标—预估—实际三层信息。顺滑的核心strokeEnd 弧绘制动画 为什么不用每帧重画一段更长的弧因为 EChart 根本不改路径。CAShapeLayer 有两个很少被用到的属性strokeStart和strokeEnd取值 0~1表示这条路径画到百分之几。EChart 的路径一开始就是最终完整的弧动画只推动一个标量CABasicAnimation *pathAnimation [CABasicAnimation animationWithKeyPath:strokeEnd]; pathAnimation.duration 2.0; pathAnimation.fromValue 0.0f; pathAnimation.toValue 1.0f;这段动画EChart/EPieChart.m中reloadContent末尾同时挂到_circleCurrent和_circleEstimate两个图层上。strokeEnd从 0 变到 1 的过程就是弧从 12 点方向顺时针生长出来的过程。为什么这样画特别顺零路径重建整场动画只插值一个浮点数不分配内存、不重算 UIBezierPath主线程几乎零负担Render Server 接管Core Animation 的隐式动画在独立的渲染进程中执行即使主线程短暂卡顿弧线也继续流畅绘制GPU 友好最终弧线只是一次 GPU 描边操作圆形路径 圆角线帽对硬件光栅化非常友好双弧天然同步预估弧和当前弧挂载同一个动画实例进度绝对一致不会出现两段弧赛跑的错位感。角度从哪来270° 起点的小秘密iOS 的坐标系统里角度 0 指向 3 点钟方向。源码中所有弧的起点都是M_PI_2 * 3即 270°也就是屏幕上的12 点钟方向终点角度比起点小270° − 比例 × 360°所以在屏幕上呈现为顺时针扫描。比例换算公式就是值 / budget × 2π——数据模型里的三个数字直接决定了每段弧扫过多少度。数字滚动也卡点UICountingLabel弧画了 2 秒中心的数字要是啪地跳出来就出戏了。EChart 用 UICountingLabel.m 解决它基于 30fps 的 NSTimer按EaseInOutrate 3缓动把 0 滚到目标值总时长同样是2.0 秒——与弧线动画的kCAMediaTimingFunctionEaseInEaseOut节奏完全一致。弧在收数字也在收快慢曲线同型这就是整体观感顺滑的另一半原因。点一下翻个面圆环图的前后交互圆环还有一层彩蛋交互单击整图触发turnPieEPieChart.m通过UIView的 Flip 转场0.3 秒把 frontPie 翻成 backPie像翻转卡片一样。你还可以实现EPieChartDataSource协议自定义正面/背面的中心内容视图设置motionEffectOn YES在 iOS 7 上获得倾斜视差效果圆环随设备轻微晃动立体感十足。快速上手运行圆环图 Demo 克隆仓库即可体验git clone https://gitcode.com/gh_mirrors/ec/EChart打开EChartDemo.xcodeprojRun 之后进入 Pie Chart 页面即可看到完整的圆环动画与翻转效果也可以参考 EChart.podspec 以 CocoaPods 方式集成。关键源码索引圆环图主体与三层弧绘制EChart/EPieChart.h、EChart/EPieChart.m数据模型budget/current/estimateEChart/EPieChart.h数字滚动动画EChart/UICountingLabel.m演示页面数据 133/33/77、手势与翻转EChartDemo/EPieChartViewController.m一句话总结EPieChart 的顺滑 完整路径一次画好 strokeEnd单标量动画 Render Server 独立渲染 数字滚动与弧线同缓动同时长。三层 CAShapeLayer 各守其位各司其职才让预算—预估—当前三层信息既清晰又丝滑。【免费下载链接】EChartiOS/iPhone/iPad Chart, Graph. Event handling and animation supported.项目地址: https://gitcode.com/gh_mirrors/ec/EChart创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考