LoaderPacmanAnimation.swift 3.88 KB
//
//  LoaderPacmanAnimation.swift
//  LoaderButton
//
//  Created by 黄进文 on 2018/6/13.
//  Copyright © 2018年 Jovins. All rights reserved.
//

import UIKit

class LoaderPacmanAnimation: LoaderButtonAnimationDelegate {

    /// Setup Loader Layer
    ///
    /// - Parameters:
    /// - layer: layer Parent layer (Button layer)
    /// - frame: frame of parant layer
    /// - color: color of Loader
    func setupLoaderButtonAnimation(layer: CALayer, frame: CGRect, color: UIColor) {

        let padding: CGFloat = 10.0
        let sizeValue: CGFloat = max(min(frame.width, frame.height) - padding, 1.0)
        createCircle(with: layer, sizeValue: sizeValue, color: color)
        createPacman(with: layer, sizeValue: sizeValue, color: color)
    }

    /// Create Pacman
    private func createPacman(with layer: CALayer, sizeValue: CGFloat, color: UIColor) {

        let padding: CGFloat = 10
        let pacmanValue: CGFloat = sizeValue
        let pacmanDuration: CFTimeInterval = 0.5
        let timingFunction = CAMediaTimingFunction(name: .default)

        /// Stroke Start Animaition
        let startAnimation = CAKeyframeAnimation(keyPath: "strokeStart")
        startAnimation.keyTimes = [0, 0.5, 1]
        startAnimation.timingFunctions = [timingFunction, timingFunction]
        startAnimation.values = [0.125, 0, 0.125]
        startAnimation.duration = pacmanDuration

        /// Stroke End Animation
        let endAnimation = CAKeyframeAnimation(keyPath: "strokeEnd")
        endAnimation.keyTimes = [0, 0.5, 1]
        endAnimation.timingFunctions = [timingFunction, timingFunction]
        endAnimation.values = [0.875, 1, 0.875]
        endAnimation.duration = pacmanDuration

        /// Group Animation
        let animation = CAAnimationGroup()
        animation.animations = [startAnimation, endAnimation]
        animation.duration = pacmanDuration
        animation.repeatCount = HUGE
        animation.isRemovedOnCompletion = false

        /// Draw Pacman
        let pacman = LoaderShape.pacman.layer(with: CGSize(width: pacmanValue, height: pacmanValue), color: color)
        let frame = CGRect(x: (sizeValue + padding - pacmanValue) * 0.5,
                           y: (sizeValue + padding - pacmanValue) * 0.5,
                           width: pacmanValue, height: pacmanValue)
        pacman.frame = frame
        pacman.add(animation, forKey: "animation")
        layer.addSublayer(pacman)
    }

    /// Create Circle
    private func createCircle(with layer: CALayer, sizeValue: CGFloat, color: UIColor) {

        let padding: CGFloat = 10.0
        let circleSize: CGFloat = sizeValue / 5
        let circleDuration: CFTimeInterval = 1.0

        /// Translate Animaton
        let translateAnimaton = CABasicAnimation(keyPath: "transform.translation.x")
        translateAnimaton.fromValue = 0
        translateAnimaton.toValue = -sizeValue * 0.5
        translateAnimaton.duration = circleDuration

        /// Opacity Animatoin
        let opacityAnimation = CABasicAnimation(keyPath: "opacity")
        opacityAnimation.fromValue = 1
        opacityAnimation.toValue = 0.75
        opacityAnimation.duration = circleDuration

        /// Animation
        let animation = CAAnimationGroup()
        animation.animations = [translateAnimaton, opacityAnimation]
        animation.timingFunction = CAMediaTimingFunction(name: .linear)
        animation.duration = circleDuration
        animation.repeatCount = HUGE
        animation.isRemovedOnCompletion = false

        /// Draw Circle
        let circle = LoaderShape.circle.layer(with: CGSize(width: circleSize, height: circleSize), color: color)
        let frame = CGRect(x: sizeValue + padding * 0.5,
                           y: (sizeValue + padding - circleSize) * 0.5,
                           width: circleSize, height: circleSize)
        circle.frame = frame
        circle.add(animation, forKey: "animation")
        layer.addSublayer(circle)
    }
}