나는 할 수있는 제스처 입력이 많은 iPhone 앱을 만들고 있습니다. 현재는 단일 손가락 선택/끌기, 두 손가락 스크롤 및 두 손가락 집기 확대/축소가 있습니다. 두 손가락 회전을 추가하고 싶습니다. (손가락이 그들 사이에 포인트를 회전 시키지만) 제대로 작동하도록하는 방법을 알 수는 없습니다. 다른 모든 제스처는 선형 이었기 때문에 점이나 십자가를 사용하는 문제였습니다.아이폰에서 두 손가락 회전 동작?
각 손가락의 이전 두 점 사이에 기울기를 저장해야한다고 생각합니다. 벡터 사이의 각도가 90 근처에 있으면 회전 할 가능성이 있습니다. 다음 손가락 동작 각도가 90 근처에 있고 한 손가락의 벡터 방향이 긍정적으로 바뀌고 부정적으로 바뀌면 회전이 발생합니다. 문제는,이 제스처와 다른 것들 사이의 명확한 구별이 필요하다는 것입니다. 위의 내용은 충분히 제거되지 않았습니다.
제안 사항?
EDIT : 다음은 벡터 분석 방식으로 수행 한 방법입니다 (픽셀 일치에 대한 아래의 제안과는 달리 여기에서 벡터 구조체를 사용하므로 각 기능이 무엇인지 추측 할 수 있음).
//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");
}
이미지 조작이나 직접 회전/확대/축소를 수행하는 경우 위의 방법을 사용하는 것이 좋습니다. 그러나 나와 같은 사람이라면 제스처를 사용하여로드하는 데 시간이 걸리는 작업을 유발할 수 있습니다. 그러면 제스처가 몇 번 활성화 될 때까지 작업을하지 않으려 고 할 수 있습니다. 각 코드와의 차이점은 여전히 완벽하게 구분되어 있지 않으므로 가끔은 여러 번 확대해서 볼 수 있습니다.
아, 거리는 누락 된 링크입니다. 나는 그것에 대해 생각하지 않았다는 것을 믿을 수 없다. 저는 벡터의 각도와 방향에만 초점을 맞추고 있었지만, 실제로는 거리가 가장 큰 차이라고 생각합니다. 그리고 나는 이전의 터치 (확대를 위해 사용됨)에 대해 이미 알고 있었지만 그것을 지적 해 주셔서 감사합니다. – Eli