如何为自定义手势识别器实现 velocityInView: ? [英] How do I implement velocityInView: for a custom gesture recognizer?

查看:38
本文介绍了如何为自定义手势识别器实现 velocityInView: ?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在实现一个自定义的 UIGestureRecognizer 子类.

I am implementing a custom UIGestureRecognizer subclass.

我想以与 UIPanGestureRecognizer 相同的方式实现 velocityInView:.但我不知道如何去做.如何以点/秒为单位计算速度?

I would like to implement velocityInView: the same way that UIPanGestureRecognizer has done it. But I'm not sure how to go about doing it. How do I calculate the velocity in points / second?

推荐答案

首先,如果你使用 Swift,你将需要创建一个桥接头和 #import<UIKit/UIGestureRecognizerSubclass.h> 以便您可以覆盖 UIGestureRegoniser 的触摸开始/移动/取消/结束方法.如果您使用的是 Objective-C,只需将该 import 语句放在 .h 或 .m 文件中.

Firstly, if you're using Swift, you're going to need to create a Bridging Header and #import <UIKit/UIGestureRecognizerSubclass.h> so you can override UIGestureRegoniser's touches began/moved/cancelled/ended methods. If you're using Objective-C just put that import statement in the .h or .m file.

其次,一旦您创建了 UIGestureRecognizer 子类,您就需要在其中添加以下变量:

Secondly, once you've created your UIGestureRecognizer subclass you need these variables in it:

private lazy var displayLink: CADisplayLink = {
    let link = CADisplayLink(target: self, selector: Selector("timerCalled"))
    link.addToRunLoop(NSRunLoop.currentRunLoop(), forMode: NSRunLoopCommonModes)
    return link
}()

private var previousTouchLocation: CGPoint?
private var currentTouchLocation : CGPoint?

private var previousTime: Double?
private var currentTime : Double?

显示链接用于更新currentTimepreviousTime.

第三,要继续设置您需要覆盖以下方法的所有内容,我认为这完全不言自明:

Thirdly, to continue setting everything up you need to override the following methods, I think it's all fairly self-explanatory:

override func touchesBegan(touches: Set<NSObject>!, withEvent event: UIEvent!) {
    self.state = .Began
    displayLink.paused = false
}

override func touchesMoved(touches: Set<NSObject>!, withEvent event: UIEvent!) {
    if let view = self.view,
        touch = touches.first as? UITouch {
        self.state = .Changed

        let newLocation = touch.locationInView(view)
        self.previousTouchLocation = self.currentTouchLocation
        self.currentTouchLocation = newLocation
    }
}

override func touchesEnded(touches: Set<NSObject>!, withEvent event: UIEvent!) {
    self.state = .Ended
    displayLink.paused = true
}

override func touchesCancelled(touches: Set<NSObject>!, withEvent event: UIEvent!) {
    self.state = .Cancelled
    displayLink.paused = true
}

第四,现在我们可以进入更有趣的部分 - 计算速度:

Fourthly, now we can get to the more interesting bit - calculating the velocity:

func velocityInView(targetView: UIView) -> CGPoint {
    var velocity = CGPoint.zeroPoint

    if let view = self.view,
        prevTouchLocation = self.previousTouchLocation,
        currTouchLocation = self.currentTouchLocation,
        previousTime = self.previousTime,
        currentTime  = self.currentTime {

        let targetPrevLocation = view.convertPoint(prevTouchLocation, toView: targetView)
        let targetCurrLocation = view.convertPoint(currTouchLocation, toView: targetView)

        let deltaTime = CGFloat(currentTime - previousTime)

        let velocityX = (targetCurrLocation.x - targetPrevLocation.x) / deltaTime
        let velocityY = (targetCurrLocation.y - targetPrevLocation.y) / deltaTime

        velocity = CGPoint(x: velocityX, y: velocityY)
    }

    return velocity
}

使用以下公式计算速度:

The velocity is calculated using the equation:

velocity = deltaDistance / deltaTime

在本例中,获取速度的每个分量(x 和 y)并使用该方程计算每个轴的速度.如果您想组合速度的两个分量,您可以像这样使用毕达哥拉斯定理:

In this case, take each component of the velocity (x and y) and use that equation to calculate the velocity in each axis. If you wanted to combine both components of the velocity you would use Pythagoras' Theorem like so:

let distance = hypot(targetCurrLocation.x - targetPrevLocation.x, 
                     targetCurrLocation.y - targetPrevLocation.y)
let velocity = distance / deltaTime

第五,在您的视图控制器中,您现在可以添加手势识别器并使用 action 来获取在屏幕上拖动时的速度:

Fifthly, in your view controller you can now add your gesture recognizer and use action to get the velocity when dragging over the screen:

override func viewDidLoad() {
    super.viewDidLoad()

    let recognizer = VelocityGestureRecognizer(target: self, action: Selector("movedGesture:"))
    self.view.addGestureRecognizer(recognizer)
}

func movedGesture(recognizer: VelocityGestureRecognizer) {
    let v = recognizer.velocityInView(self.view)
    println("velocity = \(v)")
}

这篇关于如何为自定义手势识别器实现 velocityInView: ?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆