diff --git a/GridLogo/GridLogo.swift b/GridLogo/GridLogo.swift index e486cc8..26a603b 100644 --- a/GridLogo/GridLogo.swift +++ b/GridLogo/GridLogo.swift @@ -22,30 +22,81 @@ extension CGPoint { public class GridLogo: UIView { - var mystic: CGFloat = 4 - var turns = 9 - var xstep = [1,0,-1,0] - var ystep = [0,1,0,-1] + static let xstep = [1,0,-1,0] + static let ystep = [0,1,0,-1] - var md: CGFloat! - var strokeRatio: CGFloat! - var last: CGPoint! - var curr: CGPoint! - var scalestep: CGFloat! + static func shapeLayerWithLogoPath(strokeColor: UIColor, lineJoin: String, lineWidth: CGFloat, turns: Int, md: CGFloat) -> CAShapeLayer { + + var curr = CGPointZero + var last = CGPointZero + var scalestep: CGFloat + let path = UIBezierPath() + path.moveToPoint(curr) + + for i in 0 ..< turns { + scalestep = round((CGFloat(i) + 1) / 2.0) * CGFloat(md) + curr = CGPoint(x: CGFloat(last.x) + (scalestep * CGFloat(xstep[i % 4])), y: CGFloat(last.y) + (scalestep * CGFloat(ystep[i % 4]))).toInt() + + if i + 1 == turns { + curr = CGPoint(x: CGFloat(curr.x) - (md * CGFloat(xstep[i % 4])), y: CGFloat(curr.y) - (md * CGFloat(ystep[i % 4]))).toInt() + } + + path.addLineToPoint(curr) + last = curr + } + + let shapeLayer = CAShapeLayer() + shapeLayer.path = path.CGPath + shapeLayer.strokeColor = strokeColor.CGColor + shapeLayer.fillColor = nil + shapeLayer.lineWidth = lineWidth + shapeLayer.lineJoin = lineJoin + return shapeLayer + } - weak var bgLayer: CAShapeLayer? - weak var fgLayer: CAShapeLayer? - var pathAnimationIn: CABasicAnimation! - var pathAnimationOut: CABasicAnimation! - var pathAnimationGroup: CAAnimationGroup! + static func setupAnimation(duration: CFTimeInterval, repeatCount: Float) -> CAAnimationGroup { + + let pathAnimationIn = CABasicAnimation(keyPath: "strokeEnd") + let pathAnimationOut = CABasicAnimation(keyPath: "strokeStart") + let pathAnimationGroup = CAAnimationGroup() + + + + let startPos: CGFloat = 0.0 + let endPos: CGFloat = 1.0 + + + pathAnimationIn.fromValue = startPos + pathAnimationIn.toValue = endPos + pathAnimationIn.duration = duration / 2 + pathAnimationIn.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseIn) + + + pathAnimationOut.fromValue = startPos + pathAnimationOut.toValue = endPos + pathAnimationOut.duration = duration / 2 + pathAnimationOut.beginTime = duration / 2 + pathAnimationOut.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut) + + + pathAnimationGroup.animations = [pathAnimationIn, pathAnimationOut] + pathAnimationGroup.duration = duration + pathAnimationGroup.repeatCount = repeatCount + pathAnimationGroup.removedOnCompletion = false + pathAnimationGroup.fillMode = kCAFillModeBackwards + + return pathAnimationGroup + } - private var duration: CFTimeInterval = 5.0 - private var startPos: CGFloat = 0.0 - private var endPos: CGFloat = 1.0 + private var mystic: CGFloat = 4 + private var turns: Int + private var md: CGFloat + private let bgLayer: CAShapeLayer + private let fgLayer: CAShapeLayer + private let pathAnimationGroup: CAAnimationGroup + private var duration: CFTimeInterval private var reverses = false - private var repeatCount: Float = 14.5 - private var lineWidth: CGFloat? - + private var lineWidth: CGFloat private let fadeDuration = dispatch_time(DISPATCH_TIME_NOW, Int64(0.5 * Double(NSEC_PER_SEC))) let fadeInAnimation: CABasicAnimation = { @@ -64,80 +115,38 @@ public class GridLogo: UIView { return animation }() - public init(mystic m: CGFloat, duration d: CFTimeInterval, lineWidth lw: CGFloat = 1, bgColor: UIColor = UIColor(red: 51/255, green: 51/255, blue: 48/255, alpha: 1), fgColor: UIColor = UIColor(red: 1, green: 246/255, blue: 153/255, alpha: 1)) { - super.init(frame: CGRectZero) + public init(mystic m: CGFloat, duration d: CFTimeInterval, lineWidth lw: CGFloat = 1, bgColor: UIColor = UIColor(red: 51/255, green: 51/255, blue: 48/255, alpha: 1), fgColor: UIColor = UIColor(red: 1, green: 246/255, blue: 153/255, alpha: 1), turns t: Int = 9, repeatCount: Float = 14) { + mystic = m duration = d lineWidth = lw md = m - strokeRatio = CGFloat(md) / CGFloat(mystic) + turns = t + bgLayer = GridLogo.shapeLayerWithLogoPath(bgColor, lineJoin: kCALineJoinMiter, lineWidth: lineWidth, turns: turns, md: md) + fgLayer = GridLogo.shapeLayerWithLogoPath(fgColor, lineJoin: kCALineJoinMiter, lineWidth: lineWidth, turns: turns, md: md) + pathAnimationGroup = GridLogo.setupAnimation(duration, repeatCount: repeatCount) + + super.init(frame: CGRectZero) + layer.addSublayer(bgLayer) + layer.addSublayer(fgLayer) userInteractionEnabled = false - addBackground(bgColor) - setupAnimation(fgColor) + } required public init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } - var logoPath: UIBezierPath { - get{ - self.curr = CGPoint.zero - self.last = CGPoint.zero - let path = UIBezierPath() - path.moveToPoint(curr) - - for i in 0 ..< turns { - scalestep = round((CGFloat(i) + 1) / 2.0) * CGFloat(md) - curr = CGPoint(x: CGFloat(last.x) + (scalestep * CGFloat(xstep[i % 4])), y: CGFloat(last.y) + (scalestep * CGFloat(ystep[i % 4]))).toInt() - - if i + 1 == turns { - curr = CGPoint(x: CGFloat(curr.x) - (md * CGFloat(xstep[i % 4])), y: CGFloat(curr.y) - (md * CGFloat(ystep[i % 4]))).toInt() - } - - path.addLineToPoint(curr) - last = curr - } - return path - } - } - func setupAnimation(color: UIColor) { - if fgLayer == nil { - - let foreground = shapeLayerWithLogoPath(color, lineJoin: kCALineJoinMiter) - self.fgLayer = foreground - self.layer.addSublayer(foreground) - } - pathAnimationIn = CABasicAnimation(keyPath: "strokeEnd") - pathAnimationIn.fromValue = self.startPos - pathAnimationIn.toValue = self.endPos - pathAnimationIn.duration = self.duration / 2 - pathAnimationIn.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseIn) - - pathAnimationOut = CABasicAnimation(keyPath: "strokeStart") - pathAnimationOut.fromValue = self.startPos - pathAnimationOut.toValue = self.endPos - pathAnimationOut.duration = self.duration / 2 - pathAnimationOut.beginTime = self.duration / 2 - pathAnimationOut.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut) - - pathAnimationGroup = CAAnimationGroup() - pathAnimationGroup.animations = [pathAnimationIn, pathAnimationOut] - pathAnimationGroup.duration = self.duration - pathAnimationGroup.repeatCount = self.repeatCount - pathAnimationGroup.removedOnCompletion = false - pathAnimationGroup.fillMode = kCAFillModeBackwards - } public func show(completionHandler: (() -> Void)? = nil) { self.startAnimation() - self.fgLayer?.opacity = 1 - self.bgLayer?.opacity = 1 + self.fgLayer.opacity = 1 + self.bgLayer.opacity = 1 - self.fgLayer?.addAnimation(self.fadeInAnimation, forKey: "fade") - self.bgLayer?.addAnimation(self.fadeInAnimation, forKey: "fade") + self.fgLayer.addAnimation(self.fadeInAnimation, forKey: "fade") + self.bgLayer.addAnimation(self.fadeInAnimation, forKey: "fade") dispatch_after(self.fadeDuration, dispatch_get_main_queue()) { completionHandler?() @@ -145,51 +154,24 @@ public class GridLogo: UIView { } public func hide(completionHandler: (() -> Void)? = nil) { - self.fgLayer?.opacity = 0 - self.bgLayer?.opacity = 0 + self.fgLayer.opacity = 0 + self.bgLayer.opacity = 0 - self.fgLayer?.addAnimation(self.fadeOutAnimation, forKey: "fade") - self.bgLayer?.addAnimation(self.fadeOutAnimation, forKey: "fade") + self.fgLayer.addAnimation(self.fadeOutAnimation, forKey: "fade") + self.bgLayer.addAnimation(self.fadeOutAnimation, forKey: "fade") dispatch_after(self.fadeDuration, dispatch_get_main_queue()) { - self.fgLayer?.removeAllAnimations() + self.fgLayer.removeAllAnimations() completionHandler?() } } func startAnimation() { - self.fgLayer?.removeAllAnimations() - self.fgLayer?.addAnimation(pathAnimationGroup, forKey: "group") + self.fgLayer.removeAllAnimations() + self.fgLayer.addAnimation(pathAnimationGroup, forKey: "group") } func endAnimation() { - self.fgLayer?.removeAllAnimations() - } - - func shapeLayerWithLogoPath(strokeColor: UIColor, lineJoin: String) -> CAShapeLayer { - let shapeLayer = CAShapeLayer() - shapeLayer.path = logoPath.CGPath - shapeLayer.strokeColor = strokeColor.CGColor - shapeLayer.fillColor = nil - if lineWidth == nil { - shapeLayer.lineWidth = self.strokeRatio - } else { - shapeLayer.lineWidth = self.lineWidth! - } - shapeLayer.lineJoin = lineJoin - return shapeLayer - } - - func addBackground(color: UIColor) { - if bgLayer == nil { - let background = shapeLayerWithLogoPath(color, lineJoin: kCALineJoinMiter) - self.bgLayer = background - self.layer.addSublayer(background) - } - } - - override public func needsUpdateConstraints() -> Bool { - return true + self.fgLayer.removeAllAnimations() } - } \ No newline at end of file