首先先明确下核心动画的层级关系:
抽象类: 是创建不了实例对象的, 需要子类创建
CAAanimation(抽象类) → {
子类:
①. CAPropertyAnimation (抽象类)
②. CATransition (转场动画)
③. CAAimationGroup
CAPropertyAnimation (抽象类) → {
子类:
①. CABasicAnimation
②. CAKeyframeAnimation
CABasicAnimation → {
子类:
CASpringAnimation (iOS 9)
→ 个人理解: 需要绘制图形的可以使用此图层CAShapeLayer
1.创建需要设置图层的视图View
let animationView = UIView()
animationView.cc_size = CGSize(width: self.view.cc_width*0.8, height: self.view.cc_width*0.8)
animationView.center = self.view.center
animationView.backgroundColor = .systemOrange
self.view.addSubview(animationView)
2.创建CAShapeLayer图层 + path
①. 获取容器View尺寸
let superViewW = animationView.bounds.size.width
let superViewH = animationView.bounds.size.height
let gouLayerWH: CGFloat = 74 // 图层宽高
②. 创建图层
DispatchQueue.global().async {
// 创建钩子形状图层 Shape: Shape
let gouLayer = CAShapeLayer()
gouLayer.lineWidth = 20
gouLayer.strokeColor = UIColor.white.cgColor // 画笔颜色 gouLayer.lineCap = .round // 设置线条开端和尾部的形状
gouLayer.lineJoin = .round // 设置两条线条相交处的形状
gouLayer.fillColor = UIColor.clear.cgColor // 平铺的背景颜色
gouLayer.frame = CGRect(x: superViewW*0.5 - gouLayerWH*0.5, y: superViewH*0.5 - 16, width: gouLayerWH, height: gouLayerWH)
gouLayer.transform = CATransform3DMakeAffineTransform(CGAffineTransform(rotationAngle: -0.2)) // 由于勾子太水平, 所以旋转下(正数->顺时针)
// 钩子轨迹
let gouPath = UIBezierPath()
gouPath.move(to: CGPoint.zero)
gouPath.addLine(to: CGPoint(x: 22, y: 32))
gouPath.addLine(to: CGPoint(x: 74, y: 0))
gouLayer.path = gouPath.cgPath
animationView.layer.addSublayer(gouLayer)
// 勾子动画
let strokeAnim = self.getStrokeAniamtion(animType: .end, durtion: 1.25)
gouLayer.add(strokeAnim, forKey: nil)
3.动画
// 绘画过程中的动画; 用CABasicAnimation
func getStrokeAniamtion(animType: AnimationStrokeType, durtion: TimeInterval, timingFunction: CAMediaTimingFunction? = nil) -> CAAnimation {
// 关于 strokeStart和strokeEnd:
// -> strokeStart: 起点,默认0,支持动画; 伴随每一帧动画后, 每帧轨迹会消失
// -> strokeEnd: 结束点,默认1,支持动画; 伴随每一帧动画后, 每帧轨迹会保留
let strokeAnim = CABasicAnimation(keyPath: animType.rawValue)
strokeAnim.fromValue = 0.0
strokeAnim.toValue = 1.0
strokeAnim.repeatCount = .infinity // 无穷大
strokeAnim.duration = durtion
strokeAnim.timingFunction = timingFunction ?? CAMediaTimingFunction(name: .linear) // 设置动画节奏
return strokeAnim
}
附加:
-
beginTime : 动画开始时间,更确切应该为滞后时间,就是当动画添加到layer中滞后多久开始播放, 默认为0.0
-
kCAFillModeForwards(swift中为CAMediaTimingFillMode.forwards):保持结束时状态,需要保持结束时的状态,需要将removedOnCompletion的设置为false,removedOnCompletion的为true,即动画完成后移除。
(2). kCAFillModeBackwards(swift中为CAMediaTimingFillMode.backwards):保持开始时状态,设置为该值,将会立即执行动画的第一帧,不论是否设置了 beginTime属性。
(3). kCAFillModeBoth(swift中为CAMediaTimingFillMode.both):保持两者,实际使用中与kCAFillModeBackwards相同。
(4). kCAFillModeRemoved(swift中为CAMediaTimingFillMode.removed):移除,默认为这个值,动画将在设置的 beginTime 开始执行(如没有设置beginTime属性,则动画立即执行),动画执行完成后将会layer的改变恢复原状。
网友评论