iT邦幫忙

2018 iT 邦幫忙鐵人賽
DAY 28
0

https://ithelp.ithome.com.tw/upload/images/20180117/20107329YASEegkTOR.png

LoadingAnimation - Switch

Switch
三個點的動畫,向右移動的時候從上面,向做移動的時候從下面。


LoadingView

https://ithelp.ithome.com.tw/upload/images/20180117/20107329w7Rf8krSzM.png
三個點定義在 LoadingView 的左中右位置。

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)
    }
}

動畫原理

Switch 1 Switch 2

點在移動的時候都是順時針的,從左到右依次是 dotLayer1 dotLayer2 dotLayer3

其中 dotLayer1 向右移動了兩次,dotLayer2 向左移動了一次,dotLayer3 向左移動了一次。

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


上一篇
LoadingAnimation - Triangle
下一篇
LoadingAnimation - Walk
系列文
iOS Swift x Layout x Animation x Transition30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言