2012-05-23 6 views
12

Sprich, ich habe zwei CGRects, CGRect A und CGRect B. Mein UIView-Rahmen ist die gleiche wie CGRect B, aber ich möchte eine Animation erstellen, welche die UIView B. von Frame A ÜbergangGibt es eine Möglichkeit, die CGAffineTransform zu berechnen, die benötigt wird, um eine Ansicht von Frame A nach Frame B zu transformieren?

Ich versuche, Um dies zu tun, ändern Sie die Transform-Eigenschaft der UIView, damit ich nicht zu sehr mit dem Frame herumspielen muss. Allerdings benötige ich die CGAffineTransform, um dies zu ermöglichen. Was ist der beste Weg, um diese Transformation zu berechnen?

+0

Gibt es einen dringenden Grund, die Frame-Eigenschaft von CGRect A nach CGRect B nicht einfach zu animieren? –

+1

Nicht drücken. Der Grund dafür ist jedoch, dass der Rahmen der Ansicht statisch bleibt und Transformationen verwendet werden, um ihn zu verschieben. Dies vereinfacht die Verfolgung des Rahmens bei komplexeren Statusänderungen (z. B. Autorotation). – SpacyRicochet

+0

Interessanter Ansatz. +1 :) –

Antwort

7

Ich konnte keine Bequemlichkeitsmethode für diese Art finden, also griff ich auf erprobte und echte Matrixberechnungen zurück, um dies zu erreichen.

ein CGRect A und CGRect B gegeben, um die Transformation zu berechnen, die von A nach B gehen muß, gehen Sie wie folgt vor:

CGAffineTransform transform = CGAffineTransformTranslate(CGAffineTransformIdentity, -A.origin.x, -A.origin.y); 
transform = CGAffineTransformScale(transform, 1/A.size.width, 1/A.size.height); 
transform = CGAffineTransformScale(transform, B.size.width, B.size.height); 
transform = CGAffineTransformTranslate(transform, B.origin.x, B.origin.y); 
1

Die letzte Zeile in dem obigen Codeausschnitt geändert werden muss, wie folgt:

transform = CGAffineTransformTranslate (transform, B.origin.x*A.size.width/B.size.width, B.origin.y*A.size.height/B.size.height);

26

Die bisherigen Antworten für mich nicht funktioniert hat. Dies sollte funktionieren:

+ (CGAffineTransform) transformFromRect:(CGRect)sourceRect toRect:(CGRect)finalRect { 
    CGAffineTransform transform = CGAffineTransformIdentity; 
    transform = CGAffineTransformTranslate(transform, -(CGRectGetMidX(sourceRect)-CGRectGetMidX(finalRect)), -(CGRectGetMidY(sourceRect)-CGRectGetMidY(finalRect))); 
    transform = CGAffineTransformScale(transform, finalRect.size.width/sourceRect.size.width, finalRect.size.height/sourceRect.size.height); 

    return transform; 
} 

Swift:

func transformFromRect(from: CGRect, toRect to: CGRect) -> CGAffineTransform { 
    let transform = CGAffineTransformMakeTranslation(CGRectGetMidX(to)-CGRectGetMidX(from), CGRectGetMidY(to)-CGRectGetMidY(from)) 
    return CGAffineTransformScale(transform, to.width/from.width, to.height/from.height) 
} 
+0

einer der besten Schnipsel, die ich je gesehen habe. Gut gemacht – YichenBman

3

Hier ist eine Variation auf josema.vitaminew answer, die auch Seitenverhältnis betrachtet (nützlich, wenn Sie mit Videos oder Bildern arbeiten):

+ (CGAffineTransform)transformFromRect:(CGRect)sourceRect toRect:(CGRect)finalRect keepingAspectRatio:(BOOL)keepingAspectRatio { 
    CGAffineTransform transform = CGAffineTransformIdentity; 

    transform = CGAffineTransformTranslate(transform, -(CGRectGetMidX(sourceRect)-CGRectGetMidX(finalRect)), -(CGRectGetMidY(sourceRect)-CGRectGetMidY(finalRect))); 

    if (keepingAspectRatio) { 
     CGFloat sourceAspectRatio = sourceRect.size.width/sourceRect.size.height; 
     CGFloat finalAspectRatio = finalRect.size.width/finalRect.size.height; 

     if (sourceAspectRatio > finalAspectRatio) { 
      transform = CGAffineTransformScale(transform, finalRect.size.height/sourceRect.size.height, finalRect.size.height/sourceRect.size.height); 
     } else { 
      transform = CGAffineTransformScale(transform, finalRect.size.width/sourceRect.size.width, finalRect.size.width/sourceRect.size.width); 
     } 
    } else { 
     transform = CGAffineTransformScale(transform, finalRect.size.width/sourceRect.size.width, finalRect.size.height/sourceRect.size.height); 
    } 

    return transform; 
} 
2

A schöne Swift 3 Lösung:

extension CGAffineTransform { 
    init(from: CGRect, toRect to: CGRect) { 
     self.init(translationX: to.midX-from.midX, y: to.midY-from.midY) 
     self = self.scaledBy(x: to.width/from.width, y: to.height/from.height) 
    } 
}