2012-05-23 12 views
12

decir que tengo dos CGRects, CGRect A y B. marco de CGRect Mi UIView es la misma que CGRect B, pero quiero crear una animación que muestra la transición de UIView marco de A a B.¿Hay alguna forma de calcular el CGAffineTransform necesario para transformar una vista del cuadro A al cuadro B?

Estoy intentando para hacer esto cambiando la propiedad de transformación de UIView, para no tener que perder demasiado tiempo con su marco. Sin embargo, necesito CGAffineTransform para que esto sea posible. ¿Cuál es la mejor manera de calcular esta transformación?

+0

¿Hay alguna razón apremiante para no simplemente animar la propiedad de marco de CGRect A a CGRect B? –

+1

No presionando. Pero la razón es que mantener estática la estructura de la vista y usar transformadas para moverla simplifica significativamente el seguimiento de la misma durante los cambios de estado más complejos (como la rotación automática). – SpacyRicochet

+0

Enfoque interesante. +1 :) –

Respuesta

7

No he podido encontrar un método de conveniencia de ningún tipo para esto, así que recurrí a cálculos de matriz probada y verdadera para lograr esto.

Dado un CGRect A y CGRect B, para calcular la transformación necesaria para ir de A a B, haga lo siguiente:

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

La última línea del código anterior tiene que ser cambiado de la siguiente manera:

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

26

Las respuestas anteriores no funcionan para mí. Esto debería funcionar:

+ (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

uno de los mejores fragmentos que me he encontrado. Bien hecho – YichenBman

3

Aquí hay una variación en josema.vitaminew answer que también considera la relación de aspecto (útil si se está trabajando con vídeos o imágenes):

+ (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 buena solución de Swift 3:

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) 
    } 
} 
Cuestiones relacionadas