打勾动画效果

2020-09-04  本文已影响0人  91阿生

首先先明确下核心动画的层级关系:

抽象类: 是创建不了实例对象的, 需要子类创建

CAAanimation(抽象类) → {
子类:
①. CAPropertyAnimation (抽象类)
②. CATransition (转场动画)
③. CAAimationGroup

CAPropertyAnimation (抽象类) → {
子类:
①. CABasicAnimation
②. CAKeyframeAnimation

CABasicAnimation → {
子类:
CASpringAnimation (iOS 9)

勾.gif

→ 个人理解: 需要绘制图形的可以使用此图层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
 }
附加:
  1. beginTime : 动画开始时间,更确切应该为滞后时间,就是当动画添加到layer中滞后多久开始播放, 默认为0.0

  2. 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的改变恢复原状。

上一篇 下一篇

猜你喜欢

热点阅读