在iPhone双指旋转手势?(Two-finger rotation gesture on the

2019-08-01 19:35发布

我工作的一个iPhone应用程序有很多不同的手势输入,你可以做。 目前有单指选择/拖动,双指滚动和双指捏放大/缩小。 我想在两个手指旋转(手指旋转,它们之间的点)添加,但我无法弄清楚如何得到它的工作的权利。 所有其他手势是线性的,因此他们只能使用点或交叉的产品,相当多的问题。

我想我一定要存储每个手指的前两个点之间的斜率,而如果向量之间的角度是接近90,那么有一个旋转的可能性。 如果下一个手指运动角度也接近90和载体上的一个手指的方向积极变化和不利变化,那么你已经有了一个旋转。 问题是,我需要这个手势和其他的人之间的真正区别干净 - 和上面是远远不够删除。

有什么建议?

编辑:这是我如何做它在一个矢量分析方式(而不是建议低于约匹配像素,请注意,我用我的矢量结构在这里,你应该可以猜到每个函数做什么):

//First, find the vector formed by the first touch's previous and current positions.
struct Vector2f firstChange = getSubtractedVector([theseTouches get:0], [lastTouches get:0]);
//We're going to store whether or not we should scroll.
BOOL scroll = NO;

//If there was only one touch, then we'll scroll no matter what.
if ([theseTouches count] <= 1)
{
    scroll = YES;
}
//Otherwise, we might scroll, scale, or rotate.
else
{
    //In the case of multiple touches, we need to test the slope between the two touches.
    //If they're going in roughly the same direction, we should scroll. If not, zoom.
    struct Vector2f secondChange = getSubtractedVector([theseTouches get:1], [lastTouches get:1]);

    //Get the dot product of the two change vectors.
    float dotChanges = getDotProduct(&firstChange, &secondChange);

    //Get the 2D cross product of the two normalized change vectors.
    struct Vector2f normalFirst = getNormalizedVector(&firstChange);
    struct Vector2f normalSecond = getNormalizedVector(&secondChange);
    float crossChanges = getCrossProduct(&normalFirst, &normalSecond);

    //If the two vectors have a cross product that is less than cosf(30), then we know the angle between them is 30 degrees or less.
    if (fabsf(crossChanges) <= SCROLL_MAX_CROSS && dotChanges > 0)
    {
        scroll = YES;
    }
    //Otherwise, they're in different directions so we should zoom or rotate.
    else
    {
        //Store the vectors represented by the two sets of touches.
        struct Vector2f previousDifference = getSubtractedVector([lastTouches  get:1], [lastTouches  get:0]);
        struct Vector2f currentDifference  = getSubtractedVector([theseTouches get:1], [theseTouches get:0]);

        //Also find the normals of the two vectors.
        struct Vector2f previousNormal = getNormalizedVector(&previousDifference);
        struct Vector2f currentNormal  = getNormalizedVector(&currentDifference );

        //Find the distance between the two previous points and the two current points.
        float previousDistance = getMagnitudeOfVector(&previousDifference);
        float currentDistance  = getMagnitudeOfVector(&currentDifference );

        //Find the angles between the two previous points and the two current points.
        float angleBetween = atan2(previousNormal.y,previousNormal.x) - atan2(currentNormal.y,currentNormal.x);

        //If we had a short change in distance and the angle between touches is a big one, rotate.
        if ( fabsf(previousDistance - currentDistance) <= ROTATE_MIN_DISTANCE && fabsf(angleBetween) >= ROTATE_MAX_ANGLE)
        {
            if (angleBetween > 0)
            {
                printf("Rotate right.\n");
            }
            else
            {
                printf("Rotate left.\n");
            }
        }
        else
        {
            //Get the dot product of the differences of the two points and the two vectors.
            struct Vector2f differenceChange = getSubtracted(&secondChange, &firstChange);
            float dotDifference = getDot(&previousDifference, &differenceChange);
            if (dotDifference > 0)
            {
                printf("Zoom in.\n");
            }
            else
            {
                printf("Zoom out.\n");
            }
        }
    }
}

if (scroll)
{
    prinf("Scroll.\n");
}

你应该注意的是,如果你只是在做图像处理或直接旋转/缩放功能,那么上面的方法应该是罚款。 但是,如果你和我一样,你用手势引起一些需要时间来加载,那么很可能是你要避免做的动作,直到手势连续被激活了几次。 每个我的代码之间的差异仍然是不完全分开的,所以偶尔在一堆变焦镜头的你会得到一个旋转,反之亦然。

Answer 1:

我已经找到了两个手指之间以前和当前距离,以前和当前线之间的角度这么做过。 然后我找到一些经验阈值的距离三角洲和θ角,并已经制定了非常适合我。

如果距离比我阈值,并且所述角度小于我阈值时,我缩放的图像。 否则,我将其转动。 2指滚动似乎很容易分辨。

BTW的情况下,你实际上是存储的值,该触摸已经存储在先分值。

CGPoint previousPoint1 = [self scalePoint:[touch1 previousLocationInView:nil]];
CGPoint previousPoint2 = [self scalePoint:[touch2 previousLocationInView:nil]];
CGPoint currentPoint1 = [self scalePoint:[touch1 locationInView:nil]];
CGPoint currentPoint2 = [self scalePoint:[touch2 locationInView:nil]];


Answer 2:

两个手指,两个移动,opposit(ISH)的方向。 什么姿势与此相冲突?

捏/变焦我想接近,但而捏/变焦将开始从中心点移开(如果从每行向后跟踪,你线将平行和关闭),旋转最初将有平行线(向后追踪)这将是远离彼此和那些行会不断地变化斜率(同时保持距离)。

编辑:你知道 - 这两个可以用相同的算法来解决。

而不是计算线,计算每个耙指下面的像素。 如果手指移动,从而使两个初始像素仍然是两个手指下转换图像。

这解决了所有两个手指操作,包括滚动。

双指滚动或缩小可能看起来有点摇摇晃晃的时间,因为它会做其他操作为好,但这是地图应用程序中如何似乎工作(不包括它不具有旋转)。



文章来源: Two-finger rotation gesture on the iPhone?