Swiftgram/submodules/Display/Source/WindowPanRecognizer.swift
2019-11-14 23:27:44 +04:00

82 lines
2.6 KiB
Swift

import Foundation
import UIKit
public final class WindowPanRecognizer: UIGestureRecognizer {
public var began: ((CGPoint) -> Void)?
public var moved: ((CGPoint) -> Void)?
public var ended: ((CGPoint, CGPoint?) -> Void)?
private var previousPoints: [(CGPoint, Double)] = []
override public func reset() {
super.reset()
self.previousPoints.removeAll()
}
private func addPoint(_ point: CGPoint) {
self.previousPoints.append((point, CACurrentMediaTime()))
if self.previousPoints.count > 6 {
self.previousPoints.removeFirst()
}
}
private func estimateVerticalVelocity() -> CGFloat {
let timestamp = CACurrentMediaTime()
var sum: CGFloat = 0.0
var count = 0
if self.previousPoints.count > 1 {
for i in 1 ..< self.previousPoints.count {
if self.previousPoints[i].1 >= timestamp - 0.1 {
sum += (self.previousPoints[i].0.y - self.previousPoints[i - 1].0.y) / CGFloat(self.previousPoints[i].1 - self.previousPoints[i - 1].1)
count += 1
}
}
}
if count != 0 {
return sum / CGFloat(count * 5)
} else {
return 0.0
}
}
override public func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent) {
super.touchesBegan(touches, with: event)
if let touch = touches.first {
let location = touch.location(in: self.view)
self.addPoint(location)
self.began?(location)
}
}
override public func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent) {
super.touchesMoved(touches, with: event)
if let touch = touches.first {
let location = touch.location(in: self.view)
self.addPoint(location)
self.moved?(location)
}
}
override public func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent) {
super.touchesEnded(touches, with: event)
if let touch = touches.first {
let location = touch.location(in: self.view)
self.addPoint(location)
self.ended?(location, CGPoint(x: 0.0, y: self.estimateVerticalVelocity()))
}
}
override public func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent) {
super.touchesCancelled(touches, with: event)
if let touch = touches.first {
self.ended?(touch.location(in: self.view), nil)
}
}
}