Mit UIPinchGestureRecognizer zu skalieren uiviews in eine einzige Richtung
Ich würde gerne wissen, wie wir Sie nutzen können UIPinchGestureRecognizer
zu skalieren UIView
im Einzelzimmer (x-oder y -) Richtungen allein. Sagen, wenn der Benutzer bewegte seine zwei Finger pinch-Geste nur in einer einzigen Richtung (horizontal), nur die Breite der uiview sollte erhöhen/verringern und, wenn die Finger bewegt werden, nur vertikal, die Höhe sollte sich ändern. Wenn die Finger Diagonal bewegen, dann Höhe und Breite von uiview sollte erhöhen/verringern. Ich habe gesehen, das MoveMe sample code von Apple.
UIPinchGestureRecognizer *pinchGesture = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(scalePiece:)];
[pinchGesture setDelegate:self];
[piece addGestureRecognizer:pinchGesture];
[pinchGesture release];
Stück Maßstab:
- (void)scalePiece:(UIPinchGestureRecognizer *)gestureRecognizer
{
UIView *piece = (UIView *) [gestureRecognizer view];
NSLog(@"scalePiece enter");
if ([gestureRecognizer state] == UIGestureRecognizerStateBegan){
NSLog(@"inside if");
lastTouchPosition = [gestureRecognizer locationInView:piece];
}
else if ([gestureRecognizer state] == UIGestureRecognizerStateBegan || [gestureRecognizer state] == UIGestureRecognizerStateChanged){
NSLog(@"inside else");
CGPoint currentTouchLocation = [gestureRecognizer locationInView:piece];
NSLog(@"currentTouchLocation = %@ and lastTouchPosition= %@",NSStringFromCGPoint(currentTouchLocation), NSStringFromCGPoint(lastTouchPosition));
CGPoint deltaMove = [self calculatePointDistancewithPoint1:currentTouchLocation andPoint2:lastTouchPosition];
NSLog(@"deltaMove = %@",NSStringFromCGPoint(deltaMove));
float distance = sqrt(deltaMove.x*deltaMove.x + deltaMove.y*deltaMove.y);
NSLog(@"distance = %f",distance);
float hScale = 1 - deltaMove.x/distance * (1-gestureRecognizer.scale);
float vScale = 1 - deltaMove.y/distance * (1-gestureRecognizer.scale);
if (distance == 0) {
hScale = 1;
vScale = 1;
}
NSLog(@"[gestureRecognizer scale] = %f",[gestureRecognizer scale]);
NSLog(@"hScale = %f and vScale = %f",hScale, vScale);
piece.transform = CGAffineTransformScale([piece transform], hScale, vScale);
[gestureRecognizer setScale:1];
lastTouchPosition = currentTouchLocation;
}
NSLog(@"scalePiece exit");
}
Entfernung berechnen,:
- (CGPoint) calculatePointDistancewithPoint1:(CGPoint)point1 andPoint2:(CGPoint) point2 {
return CGPointMake(point2.x - point1.x, point2.y - point1.y);
}
Dies ist die log-Ausgabe wenn ich versuche zu kneifen aus (zoom-in), die Ansicht, nur bewegte meine Finger in vertikaler Richtung. Die element-Höhe nicht erhöhen.
2011-07-21 13:06:56.245 New[8169:707] scalePiece enter
2011-07-21 13:06:56.248 New[8169:707] inside if
2011-07-21 13:06:56.251 New[8169:707] scalePiece exit
2011-07-21 13:06:56.259 New[8169:707] scalePiece enter
2011-07-21 13:06:56.262 New[8169:707] inside else
2011-07-21 13:06:56.264 New[8169:707] currentTouchLocation = {88, 87} and lastTouchPosition= {87, 86}
2011-07-21 13:06:56.265 New[8169:707] deltaMove = { -1, -1}
2011-07-21 13:06:56.267 New[8169:707] distance = 1.414214
2011-07-21 13:06:56.268 New[8169:707] [gestureRecognizer scale] = 1.102590
2011-07-21 13:06:56.271 New[8169:707] hScale = 0.927458 and vScale = 0.927458
2011-07-21 13:06:56.272 New[8169:707] scalePiece exit
2011-07-21 13:06:56.281 New[8169:707] scalePiece enter
2011-07-21 13:06:56.283 New[8169:707] inside else
2011-07-21 13:06:56.284 New[8169:707] currentTouchLocation = {87, 89} and lastTouchPosition= {88, 87}
2011-07-21 13:06:56.286 New[8169:707] deltaMove = {1, -2}
2011-07-21 13:06:56.287 New[8169:707] distance = 2.236068
2011-07-21 13:06:56.296 New[8169:707] [gestureRecognizer scale] = 1.096172
2011-07-21 13:06:56.298 New[8169:707] hScale = 1.043009 and vScale = 0.913981
2011-07-21 13:06:56.299 New[8169:707] scalePiece exit
2011-07-21 13:06:56.302 New[8169:707] scalePiece enter
2011-07-21 13:06:56.303 New[8169:707] inside else
2011-07-21 13:06:56.305 New[8169:707] currentTouchLocation = {88, 89} and lastTouchPosition= {87, 89}
2011-07-21 13:06:56.309 New[8169:707] deltaMove = { -1, 0}
2011-07-21 13:06:56.311 New[8169:707] distance = 1.000000
2011-07-21 13:06:56.313 New[8169:707] [gestureRecognizer scale] = 1.066320
2011-07-21 13:06:56.314 New[8169:707] hScale = 0.933680 and vScale = 1.000000
2011-07-21 13:06:56.316 New[8169:707] scalePiece exit
2011-07-21 13:06:56.318 New[8169:707] scalePiece enter
2011-07-21 13:06:56.320 New[8169:707] inside else
2011-07-21 13:06:56.329 New[8169:707] currentTouchLocation = {88, 90} and lastTouchPosition= {88, 89}
2011-07-21 13:06:56.331 New[8169:707] deltaMove = {0, -1}
2011-07-21 13:06:56.333 New[8169:707] distance = 1.000000
2011-07-21 13:06:56.334 New[8169:707] [gestureRecognizer scale] = 1.061696
2011-07-21 13:06:56.335 New[8169:707] hScale = 1.000000 and vScale = 0.938304
2011-07-21 13:06:56.338 New[8169:707] scalePiece exit
2011-07-21 13:06:56.343 New[8169:707] scalePiece enter
2011-07-21 13:06:56.346 New[8169:707] inside else
2011-07-21 13:06:56.347 New[8169:707] currentTouchLocation = {88, 92} and lastTouchPosition= {88, 90}
2011-07-21 13:06:56.349 New[8169:707] deltaMove = {0, -2}
2011-07-21 13:06:56.350 New[8169:707] distance = 2.000000
2011-07-21 13:06:56.351 New[8169:707] [gestureRecognizer scale] = 1.096869
2011-07-21 13:06:56.353 New[8169:707] hScale = 1.000000 and vScale = 0.903131
2011-07-21 13:06:56.362 New[8169:707] scalePiece exit
2011-07-21 13:06:56.366 New[8169:707] scalePiece enter
2011-07-21 13:06:56.370 New[8169:707] inside else
2011-07-21 13:06:56.373 New[8169:707] currentTouchLocation = {88, 92} and lastTouchPosition= {88, 92}
2011-07-21 13:06:56.376 New[8169:707] deltaMove = {0, 0}
2011-07-21 13:06:56.380 New[8169:707] distance = 0.000000
2011-07-21 13:06:56.383 New[8169:707] [gestureRecognizer scale] = 1.035330
2011-07-21 13:06:56.387 New[8169:707] hScale = 1.000000 and vScale = 1.000000
2011-07-21 13:06:56.389 New[8169:707] scalePiece exit
2011-07-21 13:06:56.393 New[8169:707] scalePiece enter
2011-07-21 13:06:56.397 New[8169:707] inside else
2011-07-21 13:06:56.399 New[8169:707] currentTouchLocation = {88, 93} and lastTouchPosition= {88, 92}
2011-07-21 13:06:56.403 New[8169:707] deltaMove = {0, -1}
2011-07-21 13:06:56.406 New[8169:707] distance = 1.000000
2011-07-21 13:06:56.409 New[8169:707] [gestureRecognizer scale] = 1.042659
2011-07-21 13:06:56.412 New[8169:707] hScale = 1.000000 and vScale = 0.957341
2011-07-21 13:06:56.414 New[8169:707] scalePiece exit
2011-07-21 13:06:56.419 New[8169:707] scalePiece enter
2011-07-21 13:06:56.422 New[8169:707] inside else
2011-07-21 13:06:56.425 New[8169:707] currentTouchLocation = {88, 92} and lastTouchPosition= {88, 93}
2011-07-21 13:06:56.427 New[8169:707] deltaMove = {0, 1}
2011-07-21 13:06:56.430 New[8169:707] distance = 1.000000
2011-07-21 13:06:56.432 New[8169:707] [gestureRecognizer scale] = 1.024549
2011-07-21 13:06:56.436 New[8169:707] hScale = 1.000000 and vScale = 1.024549
2011-07-21 13:06:56.439 New[8169:707] scalePiece exit
2011-07-21 13:06:56.442 New[8169:707] scalePiece enter
2011-07-21 13:06:56.447 New[8169:707] inside else
2011-07-21 13:06:56.450 New[8169:707] currentTouchLocation = {88, 92} and lastTouchPosition= {88, 92}
2011-07-21 13:06:56.453 New[8169:707] deltaMove = {0, 0}
2011-07-21 13:06:56.455 New[8169:707] distance = 0.000000
2011-07-21 13:06:56.458 New[8169:707] [gestureRecognizer scale] = 1.007702
2011-07-21 13:06:56.460 New[8169:707] hScale = 1.000000 and vScale = 1.000000
2011-07-21 13:06:56.464 New[8169:707] scalePiece exit
2011-07-21 13:06:56.501 New[8169:707] scalePiece enter
2011-07-21 13:06:56.504 New[8169:707] inside else
2011-07-21 13:06:56.507 New[8169:707] currentTouchLocation = {89, 92} and lastTouchPosition= {88, 92}
2011-07-21 13:06:56.509 New[8169:707] deltaMove = { -1, 0}
2011-07-21 13:06:56.510 New[8169:707] distance = 1.000000
2011-07-21 13:06:56.511 New[8169:707] [gestureRecognizer scale] = 1.000283
2011-07-21 13:06:56.513 New[8169:707] hScale = 0.999717 and vScale = 1.000000
2011-07-21 13:06:56.517 New[8169:707] scalePiece exit
2011-07-21 13:06:56.566 New[8169:707] scalePiece enter
2011-07-21 13:06:56.570 New[8169:707] inside else
2011-07-21 13:06:56.572 New[8169:707] currentTouchLocation = {89, 91} and lastTouchPosition= {89, 92}
2011-07-21 13:06:56.573 New[8169:707] deltaMove = {0, 1}
2011-07-21 13:06:56.575 New[8169:707] distance = 1.000000
2011-07-21 13:06:56.576 New[8169:707] [gestureRecognizer scale] = 1.008267
2011-07-21 13:06:56.579 New[8169:707] hScale = 1.000000 and vScale = 1.008267
2011-07-21 13:06:56.582 New[8169:707] scalePiece exit
2011-07-21 13:06:56.585 New[8169:707] scalePiece enter
2011-07-21 13:06:56.586 New[8169:707] inside else
2011-07-21 13:06:56.588 New[8169:707] currentTouchLocation = {89, 91} and lastTouchPosition= {89, 91}
2011-07-21 13:06:56.589 New[8169:707] deltaMove = {0, 0}
2011-07-21 13:06:56.591 New[8169:707] distance = 0.000000
2011-07-21 13:06:56.597 New[8169:707] [gestureRecognizer scale] = 1.000000
2011-07-21 13:06:56.599 New[8169:707] hScale = 1.000000 and vScale = 1.000000
2011-07-21 13:06:56.600 New[8169:707] scalePiece exit
2011-07-21 13:06:56.603 New[8169:707] scalePiece enter
2011-07-21 13:06:56.604 New[8169:707] inside else
2011-07-21 13:06:56.606 New[8169:707] currentTouchLocation = {89, 182} and lastTouchPosition= {89, 91}
2011-07-21 13:06:56.607 New[8169:707] deltaMove = {0, -91}
2011-07-21 13:06:56.617 New[8169:707] distance = 91.000000
2011-07-21 13:06:56.620 New[8169:707] [gestureRecognizer scale] = 1.000000
2011-07-21 13:06:56.623 New[8169:707] hScale = 1.000000 and vScale = 1.000000
2011-07-21 13:06:56.626 New[8169:707] scalePiece exit
2011-07-21 13:06:56.630 New[8169:707] scalePiece enter
2011-07-21 13:06:56.632 New[8169:707] scalePiece exit
Du musst angemeldet sein, um einen Kommentar abzugeben.
Wenn ich das richtig verstehe ist deine Frage, Sie Streben an, dass die nicht-proportionale Skalierung auf der horizontalen und vertikalen Achse. In diesem Fall, die Sache kommt, um die Bereitstellung Ihrer Affin-Transformation:
mit unterschiedlichen Skalierungsfaktoren.
Einen Weg zu berechnen, ist die folgende:
definieren ivar in Ihrer Klasse zum speichern der
lastTouchPosition
;in Ihrer Geste handler werden Sie etwas wie dieses:
Alternative Art und Weise zu tun ist:
Diese nicht speichern, die bei jedem Durchlauf die aktuelle
hFloat
undvFloat
und setzen stattdessen auf die Tatsache, dass diegestureRecognizer
sammeln sich die gesamte Skala ändern. Es hat eine "absolute" zu berechnen, während die erste Implementierung stellt eine "relative" ein.Beachten Sie, dass müssen Sie auch definieren
CGPointDistance
zur Berechnung der Entfernung zwischen zwei Berührungen, und wählen Sie, in welcher Ansicht sind Sie gehen, um zu verwenden, um die Entfernung zu berechnen (yourViewHere
).EDIT:
EDIT2: über die Formel, die zum berechnen der Skalierung
Die Idee ist, die Berechnung der variation in der scale-Faktor und wenden Sie es auf die zwei Richtungen (x und y) entsprechend Ihrer relativen Variationen.
den Skalierungsfaktor delta ist:
1-gestureRecognizer.scale
;delta ist das, multipliziert mit einem Faktor, so dass es irgendwie proportional zu der Verschiebung entlang der horizontalen oder der vertikalen Achse; bei der Verschiebung null ist, wird der delta-Skala ist auch null, wenn der Hubraum gleich ist, die entlang der zwei Achsen, die Waage delta ist auch gleich entlang der zwei Achsen; ich beschloss, zu dividieren durch die
distance
, aber es gibt auch andere Möglichkeiten (wie die Division durch die Summe der beiden deltaMoves oder von der max von der deltaMoves, etc).die eingestellte delta ist schließlich subtrahiert von der aktuellen Skalierung des Elements.
locationInView:piece.superview
...locationInView:
gibt die center Punkt von der Prise. Und es ist völlig möglich, dass sich die Mitte bewegt sich nicht, während kneifen. Dies ist, was geschieht, wenn Sie eine Prise auf iOS simulator. Der center bewegt sich nicht, deltaMove ist0,0
, dann ist der Abstand 0. Und in der nächsten Zeile, die Sie versuchen, durch null zu teilen. Die hScale und vScale in NaN. Und dann die Transformation ungültig wird und die Ansicht "verschwindet".Heute stehe ich vor dem gleichen problem, und ich fand einen einfachen und kurzen Weg, dies zu tun
Erstellte ich eine benutzerdefinierte version einer UIPinchGestureRecognizer zu tun genau das, was du bist suchen für. Es nutzt die Steilheit der Linie zwischen den zwei Fingern, um zu bestimmen, die Richtung der Skala. Es hat 3 Arten: Vertikal; Horizontal; und Kombiniert(diagonal). Bitte Lesen Sie meine Hinweise auf der Unterseite.
Vergessen Sie nicht, das Protokoll auf den view-controller-header-Datei:
Hinzufügen und die Erkennung in der viewDidLoad:
Dies ist für die Verwendung in der Hauptansicht zu erfassen, die Prise; und manipulieren einer zweiten Ansicht. Auf diese Weise können Sie noch skalieren, als die Ansicht wird kleiner. Sie können es ändern, um direkt zu reagieren, um die skalierbare Ansicht.
GRENZEN: ich willkürlich wählte die Anfangsgröße meiner Sicht ist so eine Skala-Grenzwert von 2,0 würde gleich Vollbild. Meine unteren Skala liegt bei 0.1.
USER-INTERAKTION: ich mess around mit viel Interaktion mit dem Benutzer Dinge wie das ändern der Ansicht der hintergrund-Farbe und das hinzufügen/ändern von Pfeilen über die Anzeige, um zu zeigen, Richtung. Es ist wichtig, um feedback zu geben, während die Skalierung Prozess, vor allem, wenn Sie die Richtungen ändern, wie diese codes ermöglicht.
BUG: Es gibt einen bug in apples UIPinchGestureRecognizer. Es registriert UIGestureRecognizerStateBegan mit dem Hauch von 2 Fingern, wie man es erwarten würde. Aber wenn es einmal in StateBegan oder StateChanged können Sie heben mit einem finger, und der Staat bleibt. Er bewegt sich nicht zu StateEnded oder StateCancelled, bis BEIDE Finger gehoben werden. Dies erzeugt einen Fehler in meinem code und viele Kopfschmerzen! Wenn die numberOfTouches > 1 behebt es.
ZUKUNFT: Sie können die slope-Einstellungen, um die Waage in eine Richtung, oder nur 2. Wenn Sie fügen Sie die Pfeile Bildern können Sie sehen, wie Sie ändern, wie Sie drehen Sie Ihren Finger.