LoaderLineFadeAnimation.swift 3.17 KB
//
//  LoaderLineFadeAnimation.swift
//  LoaderButton
//
//  Created by 黄进文 on 2018/6/11.
//  Copyright © 2018年 Jovins. All rights reserved.
//

import UIKit

class LoaderLineFadeAnimation: 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 = 4.0

        let sizeValue = max(min(frame.width, frame.height) - padding, 1.0)
        let center = CGPoint(x: sizeValue * 0.5 + padding * 0.5, y: sizeValue * 0.5 + padding * 0.5)
        let duration: CFTimeInterval = 1.2
        let beginTime = CACurrentMediaTime()
        let beginTimes: [CFTimeInterval] = [0.12, 0.24, 0.36, 0.48, 0.6, 0.72, 0.84, 0.96]
        let timingFunction = CAMediaTimingFunction(name: .easeInEaseOut)

        /// animation
        let animation = CAKeyframeAnimation(keyPath: "opacity")
        animation.keyTimes = [0, 0.5, 1]
        animation.timingFunctions = [timingFunction, timingFunction]
        animation.values = [1, 0.1, 1]
        animation.duration = duration
        animation.repeatCount = HUGE
        animation.isRemovedOnCompletion = false

        let lineSpace: CGFloat = 2
        let lineSize = CGSize(width: max((sizeValue - 4 * lineSpace) / 8, 1.0),
                              height: max((sizeValue - 2 * lineSpace) / 3, 1.0))
        for i in 0..<8 {
            let line = lineAt(angle: CGFloat(Double.pi / 4 * Double(i)),
                              size: lineSize,
                              origin: center,
                              containerSize: CGSize(width: sizeValue, height: sizeValue),
                              color: color)
            animation.beginTime = beginTime + beginTimes[i]
            line.add(animation, forKey: "animation")
            layer.addSublayer(line)
        }
    }

    private func lineAt(angle: CGFloat, size: CGSize, origin: CGPoint, containerSize: CGSize, color: UIColor) -> CALayer {

        let radius = (containerSize.width * 0.5 - max(size.width, size.height) * 0.5) - 2
        let lineContainerSize = CGSize(width: max(size.width, size.height), height: max(size.width, size.height))
        let lineContainer = LoaderLayer()
        let lineContainFrame = CGRect(x: origin.x + radius * (cos(angle) - 0.5),
                                      y: origin.y + radius * (sin(angle) - 0.5),
                                      width: lineContainerSize.width,
                                      height: lineContainerSize.height)
        let line = LoaderShape.line.layer(with: size, color: color)
        let lineFrame = CGRect(x: (lineContainerSize.width - size.width) * 0.5,
                               y: (lineContainerSize.height - size.height) * 0.5,
                               width: size.width, height: size.height)

        lineContainer.frame = lineContainFrame
        line.frame = lineFrame
        lineContainer.addSublayer(line)
        lineContainer.sublayerTransform = CATransform3DMakeRotation(CGFloat(Double.pi * 0.5) + angle, 0, 0, 1)
        return lineContainer
    }
}