我工作的一个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(¤tDifference );
//Find the distance between the two previous points and the two current points.
float previousDistance = getMagnitudeOfVector(&previousDifference);
float currentDistance = getMagnitudeOfVector(¤tDifference );
//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");
}
你应该注意的是,如果你只是在做图像处理或直接旋转/缩放功能,那么上面的方法应该是罚款。 但是,如果你和我一样,你用手势引起一些需要时间来加载,那么很可能是你要避免做的动作,直到手势连续被激活了几次。 每个我的代码之间的差异仍然是不完全分开的,所以偶尔在一堆变焦镜头的你会得到一个旋转,反之亦然。