设计师给了一个交互动画需要实现,是项目房间模块匹配中的一个交互动效:圆球随着实线转,实线填充虚线,圆球转到顶端开始减速,越过顶端开始加速,如图:
一开始会想如何去让一个圆球绕着圆心去转,难道是需要套什么数学公式么?思考了下,iOS 动画库中并没有这种操作,然后思考了一下上面的部件层级。
部件层级
- 一个外环圆,很好实现
- 外环圆包着内环虚线
- 一个做圆环动效的实线
- 一个固定的圆球
- 一个随圆环滚动的圆球
过程拆分
外环圆和内环虚线都非常好实现,第一反应就是 CAShapeLayer
去画各种图形,并且 ShapeLayer 在性能上是优化的。
查了很久没看见有圆球绕着锚点做圆周运动的 API,于是我拿 Sketch 尝试分解了一下,如图所示:
如图所示,换了个思路,虽然没有圆球绕着锚点做圆周运动的 API,但是可以把它放在父 layer 上,然父 layer 围绕自己的圆心自转,那么这个圆球也就绕着圆心运动了。
实现
首先从最简单的开始
外圈大圆和内圈虚线圆环
确定它们的贝塞尔曲线 path 直接绘制:
1 | CGFloat bigLayerWidth = self.bounds.size.width; |
此时的效果如图所示:
内圈动画层的绘制
要画的有三个部分:
- 需要旋转的圆环
- 需要旋转的圆球父 layer
- 需要旋转的圆球
1 |
|
此时效果如图所示:
不动圆球的绘制
1 | _staticContentLayer = [CAShapeLayer layer]; |
隐藏圆球父试图开始动画
重力加速度动画,如果使用系统的 dynamic 感应系统就太麻烦了,我选择用动画选项淡入淡出模拟:
1 | - (void)makeLayersAnimated { |
最后在父控制器的 View 上添加这个 matching view:
1 | CPMatchingView *matchingView = [[CPMatchingView alloc] initWithFrame:CGRectMake(100, 100, 200, 200)]; |