两个动画都是相同的原理,CAShapeLayer + mask,第二个动画多了一个指针,设置好锚点即可。动画部分很简单,这不是重点要说的,要说的是如何在代码层面上设计好组合动画。
对于第一个动画来说,它很简单就一个动画效果;对第二个动画来说,它是转盘动画 + 指针动画组合产生的。这是两个视图view,分散在两个不同的文件中。一开始我是用OC写的,没考虑第二个的情况下,先把第一个搞定,分为计算部分 + 视图处理部分。在写第二个的时候,我发现对于旋转的计算这部分代码完全是一样的,只有视图处理部分加上了指针的处理。我要想办法把计算部分抽离出来才合理,这个时候我是用OC写的,首先想到的就是继承,显然。。。非常的不合适,没有谁应该被抽象出来,然后考虑工具类,似乎可行但觉得。。。设计层面有点过于尴尬,这个工具类其实也并不是工具一说,它只是一个负责计算的职责模块;那么最后的选择,肯定是组合了,如何组合呢?我就需要一个类,单独处理计算部分,然后有一个代理事件,计算完成让服从代理的类去处理视图部分。这个负责计算部分的类的实例作为动画视图的一个属性组合在动画视图上,似乎达到了我们先前的一个需求。在OC中这或许是比较不错的方法,但是仔细思考下,这个负责计算的类其实问题也不小:
1.虽然OC中万物皆对象,但单纯的计算模块就分化成一个类会使得类过于庞大;
2.视图对象中放入计算类对象,使得视图对象似乎是一个指挥者,而不是一个协同者;
你会发现,这个类的问题其实是OC中组合模式牵强实现的问题,但我们似乎没有太好的方法去改变OC中组合的现状。
莫慌,swift助你一臂之力。
swift中的协议使得组合模式能良好地发挥。
对应上面的例子,我们分离出旋转动画计算部分似乎非常的easy,同时swift中的协议可以带入变量,使得我们完全可以脱离了类的概念更好地发挥。
整个协议的设计非常简单,像下面这样:
//动画旋转计算协议
protocol RotaryAnimationCalculateProtocol where Self : UIView {
//配置
var rotaryVariable : RotaryVariableStruct {get set}
//服从协议的类需要对视图操作的方法
func detailView()
}
在extension中,我具体处理了计算上的事务,具体的动画参数由RotaryVariableStruct这个结构体配置,这也是swift的一个优点,对结构体的友好,使得很多地方不需要model,一切从简。
这里和OC中不同的地方,应该就是对组合方式的实现上,OC中靠类来组合,swift中协议就可以搞定,OC中需要靠别的类的引入来调用对应的能力,给人一种很强的指挥者的感觉;而swift中的协议更像是一个个插件,服从协议即获得对应的插件能力,是一种完全组合化协同的思想。
无论是从形式还是思想上,swift对组合化的实现都比OC略胜一筹。
整理了一下放到git上:旋转动画效果