利用stroke和Path動畫製作下拉刷新動畫。
首先創建一個虛線圓。
let ovalShapeLayer = CAShapeLayer()
ovalShapeLayer.strokeColor = UIColor.white.cgColor//指定path的渲染顏色
ovalShapeLayer.fillColor = UIColor.clear.cgColor//指定圓填充色
ovalShapeLayer.lineWidth = 4.0//線寬
ovalShapeLayer.lineDashPattern = [2, 3]//實線長度2,間隙長度3
let refreshRadius = frame.size.height/2 * 0.8
ovalShapeLayer.path = UIBezierPath(ovalIn: CGRect(
x: frame.size.width/2 - refreshRadius,
y: frame.size.height/2 - refreshRadius,
width: 2 * refreshRadius,
height: 2 * refreshRadius)
).cgPath//傳遞path
layer.addSublayer(ovalShapeLayer)
lineDashPattern:設置邊線的樣式,默認爲實線,傳遞一個NSNumber數組,數組中的數值依次表示虛線中,單個線的長度和空白的長度。
在scrollView滾動時,更改路徑終點的位置,progress表示下拉百分比值:
ovalShapeLayer.strokeEnd = progress
strokeEnd默認值爲1,strokeStart默認值爲0,起始值和終點值取值範圍爲0-1。
progress爲0.5時,效果如圖:
現在我們來初始化一架飛機,設置opacity初始值爲0.0。
let airplaneImage = UIImage(named: "airplane.png")!
airplaneLayer.contents = airplaneImage.cgImage
airplaneLayer.bounds = CGRect(x: 0.0, y: 0.0,
width: airplaneImage.size.width,
height: airplaneImage.size.height)
airplaneLayer.position = CGPoint(
x: frame.size.width/2 + frame.size.height/2 * 0.8,
y: frame.size.height/2)
airplaneLayer.opacity = 0.0
layer.addSublayer(airplaneLayer)
當progress改變時,修改其透明度opacity
airplaneLayer.opacity = Float(progress)
在開始刷新時,爲strokeStart和strokeEnd添加動畫,讓虛線看起來在轉圈。
let strokeStartAnimation = CABasicAnimation(
keyPath: "strokeStart")
strokeStartAnimation.fromValue = -0.5
strokeStartAnimation.toValue = 1.0
let strokeEndAnimation = CABasicAnimation(
keyPath: "strokeEnd")
strokeEndAnimation.fromValue = 0.0
strokeEndAnimation.toValue = 1.0
let strokeAnimationGroup = CAAnimationGroup()
strokeAnimationGroup.duration = 1.5
strokeAnimationGroup.repeatDuration = 5.0
strokeAnimationGroup.animations =
[strokeStartAnimation, strokeEndAnimation]
ovalShapeLayer.add(strokeAnimationGroup, forKey: nil)
同時爲飛機添加運動軌跡
let flightAnimation = CAKeyframeAnimation(keyPath: "position")
flightAnimation.path = ovalShapeLayer.path
flightAnimation.calculationMode = kCAAnimationPaced
let airplaneOrientationAnimation = CABasicAnimation(keyPath:
"transform.rotation")
airplaneOrientationAnimation.fromValue = 0
airplaneOrientationAnimation.toValue = 2.0 * .pi
let flightAnimationGroup = CAAnimationGroup()
flightAnimationGroup.duration = 1.5
flightAnimationGroup.repeatDuration = 5.0
flightAnimationGroup.animations = [flightAnimation,
airplaneOrientationAnimation]
airplaneLayer.add(flightAnimationGroup, forKey: nil)
這裏有一個新的屬性calculationMode計算模式,它有以下取值
kCAAnimationLinear:calculationMode的默認值,表示當關鍵幀爲座標點的時候,關鍵幀之間直接直線相連進行插值計算;
kCAAnimationDiscrete:離散的,就是不進行插值計算,所有關鍵幀直接逐個進行顯示;
kCAAnimationPaced:使得動畫均勻進行,而不是按keyTimes設置的或者按關鍵幀平分時間,此時keyTimes和timingFunctions無效;
kCAAnimationCubic:對關鍵幀爲座標點的關鍵幀進行圓滑曲線相連後插值計算,對於曲線的形狀還可以通過tensionValues,continuityValues,biasValues來進行調整自定義,這裏的數學原理是Kochanek–Bartels spline,這裏的主要目的是使得運行的軌跡變得圓滑;
kCAAnimationCubicPaced:看這個名字就知道和kCAAnimationCubic有一定聯繫,其實就是在kCAAnimationCubic的基礎上使得動畫運行變得均勻,就是系統時間內運動的距離相同,此時keyTimes以及timingFunctions也是無效的。
最後效果如圖: