diff --git a/AnimatedPaths/Base.lproj/LaunchScreen.storyboard b/AnimatedPaths/Base.lproj/LaunchScreen.storyboard index 2e721e1..22ff8e4 100644 --- a/AnimatedPaths/Base.lproj/LaunchScreen.storyboard +++ b/AnimatedPaths/Base.lproj/LaunchScreen.storyboard @@ -1,7 +1,12 @@ - - + + + + + - + + + @@ -13,10 +18,9 @@ - + - - + diff --git a/AnimatedPaths/Base.lproj/Main.storyboard b/AnimatedPaths/Base.lproj/Main.storyboard index 3e7afb4..9e9193c 100644 --- a/AnimatedPaths/Base.lproj/Main.storyboard +++ b/AnimatedPaths/Base.lproj/Main.storyboard @@ -1,8 +1,12 @@ - - + + + + + - + + @@ -14,28 +18,25 @@ - + - + - - - - - - - + + - + + + @@ -46,17 +47,20 @@ - + + + + - + diff --git a/AnimatedPaths/RCAnimatedPath.swift b/AnimatedPaths/RCAnimatedPath.swift index dbf7806..c320515 100644 --- a/AnimatedPaths/RCAnimatedPath.swift +++ b/AnimatedPaths/RCAnimatedPath.swift @@ -13,25 +13,15 @@ import CoreGraphics -class RCAnimatedPath -{ - //////////////////////// - // CREATE A SINGLETON // +class RCAnimatedPath{ - class var shared: RCAnimatedPath - { - struct Singleton - { + class var shared: RCAnimatedPath{ + struct Singleton{ static let instance = RCAnimatedPath() } return Singleton.instance } - // CREATE A SINGLETON // - //////////////////////// - - - var animationLayer: CALayer? var pathLayer: CAShapeLayer? @@ -50,15 +40,13 @@ class RCAnimatedPath - func drawAnimatedCustomPath(in view: UIView, path: CGPath, duration: CFTimeInterval, lineWidth: CGFloat, lineColor: UIColor) - { + func drawAnimatedCustomPath(in view: UIView, path: CGPath, duration: CFTimeInterval, lineWidth: CGFloat, lineColor: UIColor){ self.inputDuration = duration self.inputLineWidth = lineWidth self.inputLineColor = lineColor self.inputPath = path animationLayer = CALayer() - animationLayer?.frame = CGRect(x: 0, y: 0, width: view.layer.bounds.width, height: view.layer.bounds.height) view.layer.addSublayer(animationLayer!) view.clipsToBounds = true @@ -67,8 +55,7 @@ class RCAnimatedPath startAnimation() } - func drawAnimatedRectanglePath(in view: UIView, duration: CFTimeInterval, lineWidth: CGFloat, lineColor: UIColor) - { + func drawAnimatedRectanglePath(in view: UIView, duration: CFTimeInterval, lineWidth: CGFloat, lineColor: UIColor){ self.inputDuration = duration self.inputLineWidth = lineWidth self.inputLineColor = lineColor @@ -85,8 +72,7 @@ class RCAnimatedPath startAnimation() } - func drawAnimatedPolygonPath(in view: UIView, numberOfSides polygonSidesNumber: Int?, rotationAngle: CGFloat?, polygonCornerRadius: Float?, duration: CFTimeInterval, lineWidth: CGFloat, lineColor: UIColor) - { + func drawAnimatedPolygonPath(in view: UIView, numberOfSides polygonSidesNumber: Int?, rotationAngle: CGFloat?, polygonCornerRadius: Float?, duration: CFTimeInterval, lineWidth: CGFloat, lineColor: UIColor){ self.inputDuration = duration self.inputLineWidth = lineWidth self.inputLineColor = lineColor @@ -114,8 +100,7 @@ class RCAnimatedPath startAnimation() } - func drawAnimatedText(in view: UIView, with text: String, duration: CFTimeInterval, lineWidth: CGFloat, textColor: UIColor, fontName: String?, fontSize: CGFloat?) - { + func drawAnimatedText(in view: UIView, with text: String, duration: CFTimeInterval, lineWidth: CGFloat, textColor: UIColor, fontName: String?, fontSize: CGFloat?){ self.inputText = text self.inputDuration = duration self.inputLineWidth = lineWidth @@ -138,14 +123,12 @@ class RCAnimatedPath } - func setupDrawingLayer() - { + func setupDrawingLayer(){ clearLayer() if let _ = animationLayer { - let pathRect: CGRect = animationLayer!.bounds - + let pathRect: CGRect = animationLayer!.bounds.insetBy(dx: 100.0, dy: 100.0) let pathShapeLayer = CAShapeLayer() pathShapeLayer.frame = animationLayer!.bounds @@ -163,8 +146,7 @@ class RCAnimatedPath } } - func setupTextLayer(in view: UIView) - { + func setupTextLayer(in view: UIView){ clearLayer() if let _ = animationLayer @@ -219,20 +201,34 @@ class RCAnimatedPath } - private func startAnimation() - { + private func startAnimation(){ pathLayer?.removeAllAnimations() - let pathAnimation = CABasicAnimation(keyPath: "strokeEnd") - pathAnimation.duration = inputDuration - pathAnimation.fromValue = 0.0 - pathAnimation.toValue = 1.0 - pathLayer?.add(pathAnimation, forKey: "strokeEnd") +// let pathAnimation = CABasicAnimation(keyPath: "strokeEnd") +// pathAnimation.duration = inputDuration +// pathAnimation.fromValue = 0.0 +// pathAnimation.toValue = 1.0 +// pathLayer?.add(pathAnimation, forKey: "strokeEnd") + + + + let animation = CABasicAnimation(keyPath: "strokeEnd") + + animation.fromValue = 0.0 + animation.byValue = 1.0 + animation.toValue = 1.0 + animation.duration = inputDuration + + animation.fillMode = kCAFillModeForwards + animation.isRemovedOnCompletion = false + + pathLayer?.add(animation, forKey: "drawLineAnimation") + + } //freezes the animation until clearLayer() is called - func stopAnimatingWithPause() - { + func stopAnimatingWithPause(){ if let pausedTime = pathLayer?.convertTime(CACurrentMediaTime(), from: nil) { pathLayer?.speed = 0.0 @@ -241,13 +237,11 @@ class RCAnimatedPath } //clears the animation layers - func stopAnimatingWithClear() - { + func stopAnimatingWithClear(){ clearLayer() } - func clearLayer() - { + func clearLayer(){ if let _ = pathLayer { pathLayer?.removeFromSuperlayer() @@ -255,11 +249,7 @@ class RCAnimatedPath } } - - /// CREATE PATH /// - - private func rectanglePath(view: UIView) -> CGPath - { + private func rectanglePath(view: UIView) -> CGPath{ //start point - left-down corner var point = CGPoint(x: inputLineWidth/2, y: 0) let path = UIBezierPath() @@ -285,8 +275,7 @@ class RCAnimatedPath return path.cgPath } - private func polygonPath(view: UIView) -> CGPath - { + private func polygonPath(view: UIView) -> CGPath{ let path = UIBezierPath() let theta = Float(2.0 * .pi) / Float(inputPolygonSidesNumber) @@ -295,8 +284,7 @@ class RCAnimatedPath var length = squareWidth - Float(inputLineWidth) - if inputPolygonSidesNumber % 4 != 0 - { + if inputPolygonSidesNumber % 4 != 0{ length = length * cosf(theta / 2.0) + offset / 2.0 } @@ -306,8 +294,7 @@ class RCAnimatedPath var angle = Float(Double.pi) path.move(to: point) - for _ in 0 ..< inputPolygonSidesNumber - { + for _ in 0 ..< inputPolygonSidesNumber{ let x = Float(point.x) + (sideLength - offset * 2.0) * cosf(angle) let y = Float(point.y) + (sideLength - offset * 2.0) * sinf(angle) diff --git a/AnimatedPaths/ViewController.swift b/AnimatedPaths/ViewController.swift index 9f47f15..6e4b202 100644 --- a/AnimatedPaths/ViewController.swift +++ b/AnimatedPaths/ViewController.swift @@ -7,202 +7,93 @@ // import UIKit -import QuartzCore -import CoreText -import CoreGraphics -class ViewController: UIViewController, CAAnimationDelegate { - - var animationLayer: CALayer? - var pathLayer: CAShapeLayer? - var penLayer: CALayer? +class ViewController: UIViewController { + @IBOutlet weak var Segment: UISegmentedControl! + override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. - - let targetView: UIView = self.view - - RCAnimatedPath().drawAnimatedRectanglePath(in: targetView, duration: 10, lineWidth: 20, lineColor: UIColor.red) - - RCAnimatedPath().drawAnimatedPolygonPath(in: targetView, numberOfSides: 8, rotationAngle: 30, polygonCornerRadius: 8, duration: 10, lineWidth: 5, lineColor: UIColor.gray) - - RCAnimatedPath().drawAnimatedText(in: targetView, with: "K E G", duration: 10, lineWidth: 2, textColor: UIColor.blue, fontName: "anyFontName", fontSize: 50) - -// RCAnimatedPath().drawAnimatedCustomPath(in: targetView, path: myPath, duration: 15, lineWidth: 5, lineColor: UIColor.blue) - - RCAnimatedPath.shared.drawAnimatedRectanglePath(in: targetView, duration: 10, lineWidth: 20, lineColor: UIColor.red) - - -// animationLayer = CALayer() -// animationLayer?.frame = CGRect(x: 20.0, y: 40.0, width: self.view.layer.bounds.width - 40.0, height: self.view.layer.bounds.height - 84.0) -// self.view.layer.addSublayer(animationLayer!) -// -// setupDrawingLayer() -// startAnimation() - } - - func clearLayer() { - if let _ = pathLayer{ - penLayer?.removeFromSuperlayer() - pathLayer?.removeFromSuperlayer() - penLayer = nil - pathLayer = nil - } } - - func setupPenLayer() { - let penImage = UIImage(named: "noun_project_347_2")! - let pensLayer = CALayer() - pensLayer.contents = penImage.cgImage - pensLayer.anchorPoint = CGPoint.zero - pensLayer.frame = CGRect(x: 0.0, y: 0.0, width: penImage.size.width, height: penImage.size.height) - pathLayer?.addSublayer(pensLayer) - - penLayer = pensLayer - - } - - func setupDrawingLayer() { - - clearLayer() - - if let _ = animationLayer{ - let pathRect: CGRect = animationLayer!.bounds.insetBy(dx: 100.0, dy: 100.0) - let bottomLeft = CGPoint(x: pathRect.minX, y: pathRect.minY) - let topLeft = CGPoint(x: pathRect.minX, y: pathRect.minY + pathRect.height * 2.0 / 3.0) - let bottomRight = CGPoint(x: pathRect.maxX, y: pathRect.minY) - let topRight = CGPoint(x: pathRect.maxX, y: pathRect.minY + pathRect.height * 2.0 / 3.0) - let roofTip = CGPoint(x: pathRect.midX, y: pathRect.maxY) - - let path = UIBezierPath() - path.move(to: bottomLeft) - path.addLine(to: topLeft) - path.addLine(to: roofTip) - path.addLine(to: topRight) - path.addLine(to: topLeft) - path.addLine(to: bottomRight) - path.addLine(to: topRight) - path.addLine(to: bottomLeft) - path.addLine(to: bottomRight) - - let pathShapeLayer = CAShapeLayer() - pathShapeLayer.frame = animationLayer!.bounds - pathShapeLayer.bounds = pathRect - pathShapeLayer.isGeometryFlipped = true - pathShapeLayer.path = path.cgPath - pathShapeLayer.strokeColor = UIColor.black.cgColor - pathShapeLayer.fillColor = nil - pathShapeLayer.lineWidth = 10.0 - pathShapeLayer.lineJoin = kCALineJoinBevel - - animationLayer!.addSublayer(pathShapeLayer) - - pathLayer = pathShapeLayer - } - - setupPenLayer() - } - - - - func setupTextLayer() { - clearLayer() - - let font = CTFontCreateWithName("PingFangSC-Light" as CFString, 120, nil) - let attrStr = NSAttributedString(string: "Hello Swift", attributes: [kCTFontAttributeName as String: font]) - let line = CTLineCreateWithAttributedString(attrStr) - let runArray = CTLineGetGlyphRuns(line) - - let letters = CGMutablePath() - - for runIndex in 0..