Skip to content

Commit

Permalink
feat: added SkeletonAnimationBuilder to create layer animations
Browse files Browse the repository at this point in the history
  • Loading branch information
Juanpe committed Nov 18, 2017
1 parent ef48129 commit fc66cc5
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 38 deletions.
4 changes: 4 additions & 0 deletions SkeletonView.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

/* Begin PBXBuildFile section */
8933C7851EB5B820000D00A4 /* SkeletonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8933C7841EB5B820000D00A4 /* SkeletonView.swift */; };
F51DE1091FBF70A70037919A /* SkeletonAnimationBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = F51DE1081FBF70A70037919A /* SkeletonAnimationBuilder.swift */; };
F5307E2C1FAF6BC900EE67C5 /* SkeletonGradient.swift in Sources */ = {isa = PBXBuildFile; fileRef = F5307E2B1FAF6BC900EE67C5 /* SkeletonGradient.swift */; };
F5307E2E1FB0E5E400EE67C5 /* UIView+Frame.swift in Sources */ = {isa = PBXBuildFile; fileRef = F5307E2D1FB0E5E400EE67C5 /* UIView+Frame.swift */; };
F5307E301FB0EC9D00EE67C5 /* SkeletonDefaultConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = F5307E2F1FB0EC9D00EE67C5 /* SkeletonDefaultConfig.swift */; };
Expand Down Expand Up @@ -61,6 +62,7 @@
52D6D97C1BEFF229002C0205 /* SkeletonView.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SkeletonView.framework; sourceTree = BUILT_PRODUCTS_DIR; };
8933C7841EB5B820000D00A4 /* SkeletonView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SkeletonView.swift; sourceTree = "<group>"; };
AD2FAA261CD0B6D800659CF4 /* SkeletonView.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = SkeletonView.plist; sourceTree = "<group>"; };
F51DE1081FBF70A70037919A /* SkeletonAnimationBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SkeletonAnimationBuilder.swift; sourceTree = "<group>"; };
F5307E2B1FAF6BC900EE67C5 /* SkeletonGradient.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SkeletonGradient.swift; sourceTree = "<group>"; };
F5307E2D1FB0E5E400EE67C5 /* UIView+Frame.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIView+Frame.swift"; sourceTree = "<group>"; };
F5307E2F1FB0EC9D00EE67C5 /* SkeletonDefaultConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SkeletonDefaultConfig.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -140,6 +142,7 @@
F5307E331FB1068500EE67C5 /* Collections */,
F5307E341FB106A500EE67C5 /* Extensions */,
F5307E351FB106BF00EE67C5 /* Helpers */,
F51DE1081FBF70A70037919A /* SkeletonAnimationBuilder.swift */,
F5307E2F1FB0EC9D00EE67C5 /* SkeletonDefaultConfig.swift */,
F5307E2B1FAF6BC900EE67C5 /* SkeletonGradient.swift */,
F5F899E81FAB9D2B002E8FDA /* SkeletonLayer.swift */,
Expand Down Expand Up @@ -349,6 +352,7 @@
F5307E3B1FB123C100EE67C5 /* ContainsMultilineText.swift in Sources */,
F5F899E91FAB9D2B002E8FDA /* SkeletonLayer.swift in Sources */,
F5307E2E1FB0E5E400EE67C5 /* UIView+Frame.swift in Sources */,
F51DE1091FBF70A70037919A /* SkeletonAnimationBuilder.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
85 changes: 85 additions & 0 deletions Sources/SkeletonAnimationBuilder.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
//
// SkeletonAnimationBuilder.swift
// SkeletonView-iOS
//
// Created by Juanpe Catalán on 17/11/2017.
// Copyright © 2017 SkeletonView. All rights reserved.
//

import UIKit

typealias GradientAnimationPoint = (from: CGPoint, to: CGPoint)

public enum GradientDirection {
case leftRight
case rightLeft
case topBottom
case bottomTop
case topLeftBottomRight
case bottomRightTopLeft

public var slidingAnimation: SkeletonLayerAnimation {
return SkeletonAnimationBuilder().makeSlidingAnimation(with: self)
}

var startPoint: GradientAnimationPoint {
switch self {
case .leftRight:
return (from: CGPoint(x:-1, y:0.5), to: CGPoint(x:1, y:0.5))
case .rightLeft:
return (from: CGPoint(x:1, y:0.5), to: CGPoint(x:-1, y:0.5))
case .topBottom:
return (from: CGPoint(x:0.5, y:-1), to: CGPoint(x:0.5, y:1))
case .bottomTop:
return (from: CGPoint(x:0.5, y:1), to: CGPoint(x:0.5, y:-1))
case .topLeftBottomRight:
return (from: CGPoint(x:-1, y:-1), to: CGPoint(x:1, y:1))
case .bottomRightTopLeft:
return (from: CGPoint(x:1, y:1), to: CGPoint(x:-1, y:-1))
}
}

var endPoint: GradientAnimationPoint {
switch self {
case .leftRight:
return (from: CGPoint(x:0, y:0.5), to: CGPoint(x:2, y:0.5))
case .rightLeft:
return ( from: CGPoint(x:2, y:0.5), to: CGPoint(x:0, y:0.5))
case .topBottom:
return ( from: CGPoint(x:0.5, y:0), to: CGPoint(x:0.5, y:2))
case .bottomTop:
return ( from: CGPoint(x:0.5, y:2), to: CGPoint(x:0.5, y:0))
case .topLeftBottomRight:
return ( from: CGPoint(x:0, y:0), to: CGPoint(x:2, y:2))
case .bottomRightTopLeft:
return ( from: CGPoint(x:2, y:2), to: CGPoint(x:0, y:0))
}
}
}

public class SkeletonAnimationBuilder {

public init() {
}

public func makeSlidingAnimation(with direction: GradientDirection, duration: CFTimeInterval = 1.5) -> SkeletonLayerAnimation {
return { layer in

let startPointAnim = CABasicAnimation(keyPath: #keyPath(CAGradientLayer.startPoint))
startPointAnim.fromValue = NSValue(cgPoint: direction.startPoint.from)
startPointAnim.toValue = NSValue(cgPoint: direction.startPoint.to)

let endPointAnim = CABasicAnimation(keyPath: #keyPath(CAGradientLayer.endPoint))
endPointAnim.fromValue = NSValue(cgPoint: direction.endPoint.from)
endPointAnim.toValue = NSValue(cgPoint: direction.endPoint.to)

let animGroup = CAAnimationGroup()
animGroup.animations = [startPointAnim, endPointAnim]
animGroup.duration = duration
animGroup.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseIn)
animGroup.repeatCount = .infinity

return animGroup
}
}
}
38 changes: 1 addition & 37 deletions Sources/SkeletonGradient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,55 +8,19 @@

import UIKit

typealias GradientPoint = (x: CGPoint, y: CGPoint)

public enum GradientDirection {
case leftRight
case rightLeft
case topBottom
case bottomTop
case topLeftBottomRight
case bottomRightTopLeft
case topRightBottomLeft
case bottomLeftTopRight

var vector: GradientPoint {
switch self {
case .leftRight:
return (x: CGPoint(x: 0, y: 0.5), y: CGPoint(x: 1, y: 0.5))
case .rightLeft:
return (x: CGPoint(x: 1, y: 0.5), y: CGPoint(x: 0, y: 0.5))
case .topBottom:
return (x: CGPoint(x: 0.5, y: 0), y: CGPoint(x: 0.5, y: 1))
case .bottomTop:
return (x: CGPoint(x: 0.5, y: 1), y: CGPoint(x: 0.5, y: 0))
case .topLeftBottomRight:
return (x: CGPoint(x: 0, y: 0), y: CGPoint(x: 1, y: 1))
case .bottomRightTopLeft:
return (x: CGPoint(x: 1, y: 1), y: CGPoint(x: 0, y: 0))
case .topRightBottomLeft:
return (x: CGPoint(x: 1, y: 0), y: CGPoint(x: 0, y: 1))
case .bottomLeftTopRight:
return (x: CGPoint(x: 0, y: 1), y: CGPoint(x: 1, y: 0))
}
}
}

public struct SkeletonGradient {

private var gradientColors: [UIColor]
public var direction: GradientDirection

public var colors: [UIColor] {
return gradientColors
}

public init(baseColor: UIColor, secondaryColor: UIColor? = nil, direction: GradientDirection = .leftRight) {
public init(baseColor: UIColor, secondaryColor: UIColor? = nil) {
if let secondary = secondaryColor {
self.gradientColors = [baseColor, secondary, baseColor]
} else {
self.gradientColors = baseColor.makeGradient()
}
self.direction = direction
}
}
2 changes: 1 addition & 1 deletion Sources/SkeletonView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ extension UIStackView {

extension UIView {

func addSkeletonLayer(withType type: SkeletonType, usingColors colors: [UIColor], animated: Bool, animation: SkeletonLayerAnimation? = nil) {
func addSkeletonLayer(withType type: SkeletonType, usingColors colors: [UIColor], gradientDirection direction: GradientDirection? = nil, animated: Bool, animation: SkeletonLayerAnimation? = nil) {
self.skeletonLayer = SkeletonLayerFactory().makeLayer(withType: type, usingColors: colors, andHolder: self)
layer.insertSublayer(skeletonLayer!.contentLayer, at: UInt32.max)
if animated { skeletonLayer!.start(animation) }
Expand Down

0 comments on commit fc66cc5

Please sign in to comment.