How to determine true end velocity of pan gesture?

后端 未结 2 1965
暖寄归人
暖寄归人 2021-02-04 19:37

When using UIPanGestureRecognizer and detecting UIGestureRecognizerStateEnded, then the velocity of the gesture is not the true velocity. Instead, it\'

2条回答
  •  礼貌的吻别
    2021-02-04 20:18

    2019 how-to ...

    This is the only way to really know the velocity when the finger comes up:

    have some variables...

    var cat: CADisplayLink? = nil
    var prevTime = CFAbsoluteTimeGetCurrent()
    var lastKnownPosition: CGFloat = 0
    var lastKnownActualVelocity: Double = 0
    

    and then ...

    @objc func _checkVelocityEveryTrueFrame() {
        let newTime = CFAbsoluteTimeGetCurrent()
        let frameTime = newTime - prevTime
        prevTime = newTime
    
        let newPos = yourConstraint.constant
        lastKnownActualVelocity = Double(newPos - lastKnownPosition) / frameTime
        lastKnownPosition = newPos
        print("- \(frameTime) \(lastKnownPosition) \(lastKnownActualVelocity)")
    }
    
    @objc func dragOrFlick(_ p: UIPanGestureRecognizer) {
        if p.state == .began {
            cat?.invalidate()
            cat = nil
            cat = CADisplayLink(target: self,
                 selector: #selector(_checkVelocityEveryTrueFrame))
            cat?.add(to: .main, forMode: .common)
        }
    
        if p.state == .changed {
            ... p.translation(in: ...
            yourConstraint.constant = new position...
        }
    
        if p.state == .ended {
            cat?.invalidate()
            cat = nil
            let trueFinalVelocity = lastKnownActualVelocity
            print("trueFinalVelocity is truly \(trueFinalVelocity)")
        }
    }
    

    That's it. As far as I know there's no simpler way.


    + Footnote. As any game programmer will tell you, even this is a bit shoddy; it gives the platonic velocity over one frame: purists would smooth it a little over a discussable amount of frames :/ It's a tricky issue.

提交回复
热议问题