Swiftgram/submodules/TelegramBaseController/Sources/LocationBroadcastPanelWavesNode.swift
2019-08-05 15:04:45 +03:00

135 lines
4.4 KiB
Swift

import Foundation
import UIKit
import Display
import AsyncDisplayKit
import LegacyComponents
private final class LocationBroadcastPanelWavesNodeParams: NSObject {
let color: UIColor
let progress: CGFloat
init(color: UIColor, progress: CGFloat) {
self.color = color
self.progress = progress
super.init()
}
}
private func degToRad(_ degrees: CGFloat) -> CGFloat {
return degrees * CGFloat.pi / 180.0
}
final class LocationBroadcastPanelWavesNode: ASDisplayNode {
var color: UIColor {
didSet {
self.setNeedsDisplay()
}
}
private var effectiveProgress: CGFloat = 0.0 {
didSet {
self.setNeedsDisplay()
}
}
init(color: UIColor) {
self.color = color
super.init()
self.isLayerBacked = true
self.isOpaque = false
}
override func willEnterHierarchy() {
super.willEnterHierarchy()
self.pop_removeAnimation(forKey: "indefiniteProgress")
let animation = POPBasicAnimation()
animation.property = (POPAnimatableProperty.property(withName: "progress", initializer: { property in
property?.readBlock = { node, values in
values?.pointee = (node as! LocationBroadcastPanelWavesNode).effectiveProgress
}
property?.writeBlock = { node, values in
(node as! LocationBroadcastPanelWavesNode).effectiveProgress = values!.pointee
}
property?.threshold = 0.01
}) as! POPAnimatableProperty)
animation.fromValue = CGFloat(0.0) as NSNumber
animation.toValue = CGFloat(1.0) as NSNumber
animation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.linear)
animation.duration = 2.5
animation.repeatForever = true
self.pop_add(animation, forKey: "indefiniteProgress")
}
override func didExitHierarchy() {
super.didExitHierarchy()
self.pop_removeAnimation(forKey: "indefiniteProgress")
}
override func drawParameters(forAsyncLayer layer: _ASDisplayLayer) -> NSObjectProtocol? {
let t = CACurrentMediaTime()
let value: CGFloat = CGFloat(t.truncatingRemainder(dividingBy: 2.0)) / 2.0
return LocationBroadcastPanelWavesNodeParams(color: self.color, progress: value)
}
@objc override class func draw(_ bounds: CGRect, withParameters parameters: Any?, isCancelled: () -> Bool, isRasterizing: Bool) {
let context = UIGraphicsGetCurrentContext()!
if !isRasterizing {
context.setBlendMode(.copy)
context.setFillColor(UIColor.clear.cgColor)
context.fill(bounds)
}
if let parameters = parameters as? LocationBroadcastPanelWavesNodeParams {
let center = CGPoint(x: bounds.width / 2.0, y: bounds.height / 2.0)
let length: CGFloat = 9.0
context.setFillColor(parameters.color.cgColor)
let draw: (CGContext, CGFloat, Bool) -> Void = { context, pos, right in
let path = CGMutablePath()
path.addArc(center: center, radius: length * pos + 7.0, startAngle: right ? degToRad(-26.0) : degToRad(154.0), endAngle: right ? degToRad(26.0) : degToRad(206.0), clockwise: false)
let strokedArc = path.copy(strokingWithWidth: 1.65, lineCap: .round, lineJoin: .miter, miterLimit: 10.0)
context.addPath(strokedArc)
context.fillPath()
}
let position = parameters.progress
var alpha = position / 0.5
if alpha > 1.0 {
alpha = 2.0 - alpha
}
context.setAlpha(alpha * 0.7)
draw(context, position, false)
draw(context, position, true)
var progress = parameters.progress + 0.5
if progress > 1.0 {
progress = progress - 1.0
}
let largerPos = progress
var largerAlpha = largerPos / 0.5
if largerAlpha > 1.0 {
largerAlpha = 2.0 - largerAlpha
}
context.setAlpha(largerAlpha * 0.7)
draw(context, largerPos, false)
draw(context, largerPos, true)
}
}
}