LoadingAnimation – Switch
三個點的動畫,向右移動的時候從上面,向做移動的時候從下面。
LoadingView
三個點定義在 LoadingView 的左中右位置。
1 2 3 4 5 6 7 8 9 10 11 12 |
fileprivate func setupView() { for i in 0 ..< 3 { let dotLayer = CAShapeLayer() dotLayer.bounds = CGRect(x: 0, y: 0, width: lineWidth, height: lineWidth) dotLayer.path = UIBezierPath(ovalIn: dotLayer.bounds).cgPath dotLayer.position = CGPoint(x: bounds.width / CGFloat(2) * CGFloat(i), y: bounds.midY) dotLayer.fillColor = UIColor.white.cgColor dotLayer.strokeColor = UIColor.white.cgColor layer.addSublayer(dotLayer) dotGroup.append(dotLayer) } } |
動畫原理
點在移動的時候都是順時針的,從左到右依次是 dotLayer1 dotLayer2 dotLayer3
其中 dotLayer1 向右移動了兩次,dotLayer2 向左移動了一次,dotLayer3 向左移動了一次。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
fileprivate func generateGroupAnimation(path: UIBezierPath, needRmoveOnCompletion: Bool, beginTime: CFTimeInterval) -> CAAnimationGroup { let pathToLeftAnimation = CAKeyframeAnimation(keyPath: "position") pathToLeftAnimation.path = path.cgPath pathToLeftAnimation.calculationMode = kCAAnimationPaced pathToLeftAnimation.duration = animationDuration / 2.0 if needRmoveOnCompletion { pathToLeftAnimation.fillMode = kCAFillModeForwards pathToLeftAnimation.isRemovedOnCompletion = false } let delayGroupAnimation = CAAnimationGroup() delayGroupAnimation.animations = [pathToLeftAnimation] delayGroupAnimation.duration = animationDuration delayGroupAnimation.repeatCount = Float.infinity if beginTime != 0 { delayGroupAnimation.beginTime = CACurrentMediaTime() + beginTime } return delayGroupAnimation } func startLoading() { let dotLayer1: CAShapeLayer = dotGroup[0] let dotLayer2: CAShapeLayer = dotGroup[1] let dotLayer3: CAShapeLayer = dotGroup[2] let radius = bounds.width / 4 let arcCenterLeft = CGPoint(x: radius, y: bounds.midY) let arcCenterRight = CGPoint(x: bounds.width - radius, y: bounds.midY) let pathToRight1 = UIBezierPath(arcCenter: arcCenterLeft, radius: radius, startAngle: CGFloat(Double.pi), endAngle: 0, clockwise: true) let pathToRight2 = UIBezierPath(arcCenter: arcCenterRight, radius: radius, startAngle: CGFloat(Double.pi), endAngle: 0, clockwise: true) pathToRight1.append(pathToRight2) // Animation - dot to right let pathToRightAnimation = CAKeyframeAnimation(keyPath: "position") pathToRightAnimation.path = pathToRight1.cgPath pathToRightAnimation.calculationMode = kCAAnimationPaced pathToRightAnimation.duration = animationDuration pathToRightAnimation.repeatCount = Float.infinity dotLayer1.add(pathToRightAnimation, forKey: "pathToRightAnimation") // Animation - dot to left let pathToLeft1 = UIBezierPath(arcCenter: arcCenterLeft, radius: radius, startAngle: 0, endAngle: CGFloat(Double.pi), clockwise: true) let dot2Animation = generateGroupAnimation(path: pathToLeft1, needRmoveOnCompletion: true, beginTime: 0) dotLayer2.add(dot2Animation, forKey: "dot2Animation") let pathToLeft2 = UIBezierPath(arcCenter: arcCenterRight, radius: radius, startAngle: 0, endAngle: CGFloat(Double.pi), clockwise: true) let dot3Animation = generateGroupAnimation(path: pathToLeft2, needRmoveOnCompletion: false, beginTime: animationDuration / 2.0) dotLayer3.add(dot3Animation, forKey: "dot3Animation") } |
Reference
- 在 Github 上有相關的 Source Code
- STLoadingGroup