如何在iPhone上制作“iPod Wheel”型控件?

时间:2016-02-17 12:10:18

标签: objective-c swift cocoa-touch geometry

我想在我正在做的Swift项目中创建一种“iPod Wheel”控件。我已经把所有东西都画出来了,但现在不是时候让它真正起作用了。

iPod Style Wheel

当用户主动按下滚轮并沿顺时针或逆时针方向旋转他/她的拇指时,最好的方法是识别“旋转”,或者更清楚地描述“旋转”

毫无疑问,我想使用touchesBegan / touchesMoved / touchesEnded。什么是找出旋转的最佳方法?

我在想

a)通过从中心点确定半径,在touchesMoved中确定用户是否在圈内。中心点和半径很容易获得。然而,使用这些,我如何确定圆/轮的外边缘...以了解用户是否在实际圆内(他们的触摸仍然可以在视图中,但在实际的轮部分之外)

b)确定当前角度以及它如何改变先前的角度。我的意思是......我会将圆的中心点用作一个点,并将用户当前的触摸用作第二个点。这给了我我的载体。我也有一个基线角度。可能中心指向12点钟。我会比较两个向量(我已经从其他东西我已经有了一个VectorMath类)并看到我的角度是0.如果用户触摸是在3点钟,我将它与我们的基线角度进行比较...我会看到角度是90度。我会不断计算角度,也许每5度的变化......都会保证控制输出的变化(取决于所需的灵敏度)。

这似乎是最好的方法吗?我认为这将是一种理想的方式,但我仍然不确定如何计算圆形外边缘,并确定用户是否触摸它。

3 个答案:

答案 0 :(得分:2)

你走在正确的轨道上。我认为方法b)可行。

  1. 记住手指在touchesBegan处的起始位置 事件

  2. 想象一下从手指位置到按钮中间的一条线 圈。

  3. 对于touchesMoved事件,再次想象一下来自的虚拟线 新的位置到圆心。

  4. 使用公式 您可以确定http://mathworld.wolfram.com/Line-LineAngle.html(或某些code) 两条线之间的角度。如果是用户的负角度 逆时针转动轮子,否则顺时针转动。

  5. 要确定触摸事件是否在环内,请计算从圆心到触摸点的距离。它应该在最小和最大距离(内圆和外圆半径)之间。计算两点之间的距离在https://www.mathsisfun.com/algebra/distance-2-points.html

    中解释

答案 1 :(得分:1)

我认为你几乎就在那里,虽然我会在你的观点b上做些不同的事情。

如果你考虑一下,当你开始在iPod上“旋转”时,你不需要从一个精确的位置开始,你从“你开始的地方”开始旋转,因此我不会设置我的“基线”角度“在π/ 2,我在我们第一次点击的点处设置我的基线(或0°)角度,从那时开始,我将计算偏移角度,顺时针和逆时针。 我不认为会有太大的不同,除了可能从角度上做的一些计算,实际上是两种方法;从第一个输入评估开始计数比将基线设置为π/ 2并计算第一个角度更有意义imho。

答案 2 :(得分:0)

我正在部分回答。

// Get a position based on the angle
      float xPosition = center.x + (radiusX * sinf(angleInRadians)) - (CGRectGetWidth([cell frame]) / 2);
      float yPosition = center.y + (radiusY * cosf(angleInRadians)) - (CGRectGetHeight([cell frame]) / 2);

      float scale = 0.75f + 0.25f * (cosf(angleInRadians) + 1.0);

[cell setTransform:CGAffineTransformScale(CGAffineTransformMakeTranslation(xPosition, yPosition), scale, scale)];
         // Tweak alpha using the same system as applied for scale, this
         // time with 0.3 the minimum and a semicircle range of 0.5
         [cell setAlpha:(0.3f + 0.5f * (cosf(angleInRadians) + 1.0))];

- (void)spin:(SpinGestureRecognizer *)recognizer
{
   CGFloat angleInRadians = -[recognizer rotation];
   CGFloat degrees = 180.0 * angleInRadians / M_PI;   // Radians to degrees
   [self setCurrentAngle:[self currentAngle] + degrees];
   [self setAngle:[self currentAngle]];
}

再次检查github中的photowheel的wheelview.m。