iOS/Swift:检测旋转运动的自定义 UIGestureRecognizer
iOS/Swift: Custom UIGestureRecognizer that detect spin motion
嘿,我正在尝试构建一个允许我在屏幕上旋转轮子的 UIGestureRecognizer。想象一下:
必须检测两个手势:转动轮子和旋转轮子。
我已经完成了构建一个 UIGestureRecognizer 识别转动轮子,换句话说,旋转它。我还能够将 UISwipeGestureRecognizer 添加到滚轮以检测是否发生了旋转手势。但是,我还希望检测到如下所示的手势:
- 用户通过在屏幕上平移来旋转滚轮
- 平移后,手指仍放在屏幕上,快速滑动并移开屏幕手指,滚轮会旋转
我试过使用
public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return true
}
让它们同时工作,但没有成功。此外,我认为仅仅连接两个描述的 GestureRecognizers 是行不通的。
如有任何帮助,我将不胜感激。谢谢
你的问题是,当平移开始时,它将继续被识别为平移手势,直到触摸结束。所以你需要弄清楚的是平移结束时的速度,如果你想变得更漂亮,将那个速度从相对于视图中心的点投影到垂直向量上。这将涉及一些三角函数,我完全忘记了,但它看起来像这样。
func pan(_ sender: UIPanGestureRecognizer) {
...
if sender.state == .ended {
let loc = sender.location(in: sender.view)
let midpoint = CGPoint(x: sender.view!.bounds.width/2, y: sender.view!.bounds.height/2)
let v = sender.velocity(in: sender.view)
let p = CGPoint(x: midpoint.x - loc.x, y: midpoint.y - loc.y)
let angle = atan(p.y/p.x)
print(angle)
let vProjection = v.y * cos((CGFloat.pi/2 - angle)) + v.x * cos(angle)
print("moment: ", vProjection)
let torque = p.hypotenuse() * vProjection
wheel.rotate(with: torque)
}
}
extension CGPoint {
func hypotenuse() -> CGFloat {
return sqrt(self.x * self.x + self.y * self.y)
}
}
我想我的三角函数有错误。我将不得不画一些图表,但它给出了总体思路。 wheel.rotate(使用力矩:CGFloat)将 运行 层的变换动画以旋转它..
嘿,我正在尝试构建一个允许我在屏幕上旋转轮子的 UIGestureRecognizer。想象一下:
必须检测两个手势:转动轮子和旋转轮子。 我已经完成了构建一个 UIGestureRecognizer 识别转动轮子,换句话说,旋转它。我还能够将 UISwipeGestureRecognizer 添加到滚轮以检测是否发生了旋转手势。但是,我还希望检测到如下所示的手势:
- 用户通过在屏幕上平移来旋转滚轮
- 平移后,手指仍放在屏幕上,快速滑动并移开屏幕手指,滚轮会旋转
我试过使用
public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return true
}
让它们同时工作,但没有成功。此外,我认为仅仅连接两个描述的 GestureRecognizers 是行不通的。
如有任何帮助,我将不胜感激。谢谢
你的问题是,当平移开始时,它将继续被识别为平移手势,直到触摸结束。所以你需要弄清楚的是平移结束时的速度,如果你想变得更漂亮,将那个速度从相对于视图中心的点投影到垂直向量上。这将涉及一些三角函数,我完全忘记了,但它看起来像这样。
func pan(_ sender: UIPanGestureRecognizer) {
...
if sender.state == .ended {
let loc = sender.location(in: sender.view)
let midpoint = CGPoint(x: sender.view!.bounds.width/2, y: sender.view!.bounds.height/2)
let v = sender.velocity(in: sender.view)
let p = CGPoint(x: midpoint.x - loc.x, y: midpoint.y - loc.y)
let angle = atan(p.y/p.x)
print(angle)
let vProjection = v.y * cos((CGFloat.pi/2 - angle)) + v.x * cos(angle)
print("moment: ", vProjection)
let torque = p.hypotenuse() * vProjection
wheel.rotate(with: torque)
}
}
extension CGPoint {
func hypotenuse() -> CGFloat {
return sqrt(self.x * self.x + self.y * self.y)
}
}
我想我的三角函数有错误。我将不得不画一些图表,但它给出了总体思路。 wheel.rotate(使用力矩:CGFloat)将 运行 层的变换动画以旋转它..