【问题标题】:iPhone: how to quantize the position of a touched objectiPhone:如何量化触摸对象的位置
【发布时间】:2012-08-28 09:24:52
【问题描述】:

大家好,你们这些聪明人! 我想为 iOS 应用程序创建一个触摸界面,允许用户在屏幕上拖动一个对象。 然而,这个对象应该被限制为沿着一个圆的周长移动,这样如果用户试图将这个对象拖到那个路径之外,它就会粘到那个圆最近的点上。 我做过一些 iPhone 编程,但我的数学很差。请帮忙!

【问题讨论】:

  • 我真的才刚开始,所以还没有代码。我将能够找出用户触摸屏幕的位置,并且可以将位图移动到该位置。我需要知道的是如何定义一个圆,以及如何计算圆中最接近触摸点的点。

标签: iphone touch geometry quantization


【解决方案1】:

您所要做的就是将视图框架设置为遵循圆方程(形式为:(x-a)^2 + (y-b)^2 = r^2)。一旦检测到触摸点,就可以根据触摸点的 x 或 y 坐标来限制视图的框架(两种方式都是一样的)。

#define circleRadius 60.0 // r in the above eqtn
#define circlesCenter_X 160.0 // a in the above eqtn
#define circlesCenter_Y 200.0 // b in the above eqtn
#define circleCenter_y(x) sqrtf(circleRadius*circleRadius - (x-circlesCenter_X)*(x-circlesCenter_X))

-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
    UITouch *touch = [[event touchesForView:firstPieceView] anyObject];
    CGPoint previousLocation = [touch previousLocationInView:self.view];
    CGPoint location = [touch locationInView:self.view];
    CGFloat delta_x = previousLocation.x - location.x; // constrained by x in this eg.
    CGFloat newX = firstPieceView.center.x-delta_x;
    // do limit the view's x-coordinate for possible solutions
    if(newX<circlesCenter_X - circleRadius)
        newX = circlesCenter_X - circleRadius;
    if(newX>circlesCenter_X + circleRadius)
        newX = circlesCenter_X + circleRadius;
    firstPieceView.center = CGPointMake(newX, circleCenter_y(newX)*(location.y>=circlesCenter_Y?1:-1) + circlesCenter_Y);
}

EDIT-更好的解决方案:

#define circleRadius 60.0 // r in the above eqtn
#define circlesCenter_X 160.0 // a in the above eqtn
#define circlesCenter_Y 200.0 // b in the above eqtn
#define slope(x,y) (y-circlesCenter_Y)/(x-circlesCenter_X)
#define pointOnCircle_X(m) circleRadius/(sqrtf(m*m + 1))

-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
    UITouch *touch = [[event touchesForView:self.view] anyObject];
    CGPoint location = [touch locationInView:self.view];
    CGFloat slope;
    CGPoint pointOnCircle;
    if(location.x==circlesCenter_X){// case for infinite slope
        pointOnCircle.x = circlesCenter_X;
        if(location.x<circlesCenter_X){
            pointOnCircle.y = circlesCenter_Y - circleRadius;
        }else{
            pointOnCircle.y = circlesCenter_Y + circleRadius;
        }
    }else{
        slope = slope(location.x,location.y);
        if(location.x<circlesCenter_X){
            pointOnCircle.x = circlesCenter_X - pointOnCircle_X(slope);
        }else{
            pointOnCircle.x = circlesCenter_X + pointOnCircle_X(slope);
        }
        pointOnCircle.y = slope * (pointOnCircle.x - circlesCenter_X) + circlesCenter_Y;
    }
    firstPieceView.center = pointOnCircle;
}

这同样适用于AndroidBlackberry 等!

【讨论】:

  • 谢谢,这符合我高中时的记忆!我马上试试,给你打个绿勾奖励!
  • 其实这只是部分起作用:它确实做了一个圆圈的下半部分,但是一旦它进入上半部分,它就会抛出一个异常('CALayerInvalidGeometry',原因:'CALayer position contains南:[262 南]')。另外,我对“按钮”和“btnLeft”有点困惑。它们彼此之间以及与“yourView”的关系如何?
  • 实际上我是从我创建的自定义半圆形菜单中获取此代码的,因此未知变量仍然存在。现在回到例外:首先,我没有对 x 的极限设置任何条件。您得到的NaN 是当您尝试对负数求平方根时(我在答案中添加了条件)。此外,由于这是一个二次方程,它有两个解!我已经编辑了答案以包含它!
  • 亲爱的tipycalFlow,非常感谢您的努力!冒着让自己完全傻瓜的风险,这就是我所做的:我以 Apple 的 Touches 示例 (developer.apple.com/library/ios/#samplecode/Touches/…) 为例,并用你的方法替换了 touchesMoved 方法。我用 firstPieceView 替换了 yourView。不知何故,firstPieceView 只是在触摸时不会移动。然后我用 self.view 替换了 yourView,作为一个实验。 [继续]
  • 这移动了整个 viewController,这不是我所需要的,但它至少表明,移动似乎仍然被限制在圆的下半部分,不过这次无一例外。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-09
  • 1970-01-01
相关资源
最近更新 更多