Created
February 25, 2023 23:27
-
-
Save kylehowells/9681243715760e06ae276ad50f40789c to your computer and use it in GitHub Desktop.
Revisions
-
kylehowells created this gist
Feb 25, 2023 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,112 @@ import UIKit // MARK: - WaveView class WaveView: UIView { private var shapeLayer: CAShapeLayer = CAShapeLayer() // MARK: - Animation Properties /// 0 - Static /// 20 - Very fast var speed: CGFloat = 10 /// Wave Height var frequency: CGFloat = 6.0 /// Wave phase private var phase: CGFloat = 0.0 /// Wave color var preferredColor: UIColor = UIColor.cyan { didSet { self.shapeLayer.fillColor = self.preferredColor.cgColor self.shapeLayer.strokeColor = self.preferredColor.cgColor } } // MARK: - Start Animation enum Direction { case right case left } func animationStart(direction: Direction, speed: Double) { self.preferredColor = UIColor.cyan self.layer.addSublayer(self.shapeLayer) if direction == .right { self.speed = -speed } else { self.speed = speed } self.startDisplayLink() } // MARK: - Display Link private weak var displayLink: CADisplayLink? private var startTime: CFTimeInterval = 0 private func startDisplayLink() { self.startTime = CACurrentMediaTime() self.displayLink?.invalidate() let displayLink = CADisplayLink(target: self, selector:#selector(self.handleDisplayLink(_:))) displayLink.add(to: .main, forMode: .common) self.displayLink = displayLink } @objc private func handleDisplayLink(_ displayLink: CADisplayLink) { self.phase = (CACurrentMediaTime() - self.startTime) * self.speed self.updatePath() } private func stopDisplayLink() { self.displayLink?.invalidate() } // MARK: - Layout override func layoutSubviews() { super.layoutSubviews() self.shapeLayer.frame = self.bounds self.updatePath() } func updatePath() { let path: UIBezierPath = UIBezierPath() let width: CGFloat = self.bounds.width let height: CGFloat = self.bounds.height let mid: CGFloat = height * 0.25 let waveLength: CGFloat = width / self.frequency let waveHeightCoef: CGFloat = self.frequency path.move(to: CGPoint(x: 0, y: self.bounds.maxY)) path.addLine(to: CGPoint(x: 0, y: mid)) for x in stride(from: 0, through: width, by: 1) { let actualX: CGFloat = x / waveLength let sine: CGFloat = -sin((actualX + self.phase)) let y: CGFloat = waveHeightCoef * sine + mid path.addLine(to: CGPoint(x: x, y: y)) } path.addLine(to: CGPoint(x: CGFloat(width), y: self.bounds.maxY)) path.addLine(to: CGPoint(x: 0, y: self.bounds.maxY)) self.shapeLayer.path = path.cgPath } }