125 lines
3.5 KiB
Swift
125 lines
3.5 KiB
Swift
//
|
|
// ConnectionCirclesView.swift
|
|
// PrivadoVPN
|
|
//
|
|
// Created by Zhandos Bolatbekov on 07.07.2021.
|
|
// Copyright © 2021 Privado LLC. All rights reserved.
|
|
//
|
|
|
|
import UIKit
|
|
|
|
final class ConnectionCirclesView: BaseView {
|
|
|
|
private enum Constants {
|
|
|
|
enum Geometry {
|
|
static let minCircleDiameter: CGFloat = 418
|
|
static let diameterShift: CGFloat = 208
|
|
}
|
|
|
|
enum Color {
|
|
static let circle = UIColor(rgb: 0xA2A9D2)
|
|
}
|
|
|
|
static let minCircleOpacity: CGFloat = 0.1
|
|
static let opacityShift: CGFloat = 0.02
|
|
static let animationInterval: TimeInterval = 0.5
|
|
}
|
|
|
|
private var animationScheduler: Timer?
|
|
private let circlesCount: Int
|
|
private var circleLayers = [CALayer]()
|
|
private var allCirclesHidden = false
|
|
|
|
// MARK: - Init
|
|
|
|
init(circlesCount: Int) {
|
|
self.circlesCount = circlesCount
|
|
super.init()
|
|
|
|
self.translatesAutoresizingMaskIntoConstraints = false
|
|
}
|
|
|
|
// MARK: - Lifecycle
|
|
|
|
override func layoutSubviews() {
|
|
super.layoutSubviews()
|
|
|
|
self.drawCircles()
|
|
self.hideCircles(all: self.allCirclesHidden)
|
|
}
|
|
|
|
// MARK: - Interface
|
|
|
|
func startAnimating() {
|
|
guard !self.animationScheduler.isExist else { return }
|
|
|
|
let scheduler = Timer.scheduledTimer(withTimeInterval: Constants.animationInterval, repeats: true) { [weak self] _ in
|
|
self?.updateToNextState()
|
|
}
|
|
self.animationScheduler = scheduler
|
|
}
|
|
|
|
func stopAnimating() {
|
|
if let scheduler = self.animationScheduler {
|
|
scheduler.invalidate()
|
|
scheduler.fire()
|
|
}
|
|
|
|
self.animationScheduler = nil
|
|
self.hideCircles()
|
|
}
|
|
|
|
func resetState() {
|
|
self.hideCircles(all: true)
|
|
self.allCirclesHidden = true
|
|
}
|
|
|
|
// MARK: - Private
|
|
|
|
private func updateToNextState() {
|
|
self.allCirclesHidden = false
|
|
self.circleLayers.first?.isHidden = false
|
|
|
|
var newCircleAppeared = false
|
|
for i in 1..<self.circlesCount {
|
|
if self.circleLayers[safe: i]?.isHidden == true {
|
|
self.circleLayers[safe: i]?.isHidden = false
|
|
newCircleAppeared = true
|
|
break
|
|
}
|
|
}
|
|
if !newCircleAppeared {
|
|
self.hideCircles()
|
|
}
|
|
}
|
|
|
|
private func hideCircles(all: Bool = false) {
|
|
for i in (all ? 0 : 1)..<self.circlesCount {
|
|
self.circleLayers[safe: i]?.isHidden = true
|
|
}
|
|
if !all {
|
|
self.circleLayers[safe: 0]?.isHidden = false
|
|
}
|
|
}
|
|
|
|
private func drawCircles() {
|
|
self.circleLayers.forEach {
|
|
$0.removeFromSuperlayer()
|
|
}
|
|
self.circleLayers.removeAll()
|
|
|
|
for i in 0..<self.circlesCount {
|
|
let size = Constants.Geometry.minCircleDiameter + Constants.Geometry.diameterShift * CGFloat(i)
|
|
let rect = CGRect(x: self.center.x - size / 2, y: self.center.y - size / 2, width: size, height: size)
|
|
let path = UIBezierPath(ovalIn: rect)
|
|
let shapeLayer = CAShapeLayer()
|
|
shapeLayer.path = path.cgPath
|
|
shapeLayer.fillColor = Constants.Color.circle
|
|
.withAlphaComponent(Constants.minCircleOpacity - Constants.opacityShift * CGFloat(i)).cgColor
|
|
self.layer.addSublayer(shapeLayer)
|
|
self.circleLayers.append(shapeLayer)
|
|
}
|
|
}
|
|
}
|