2012-05-23 32 views
12

說,我有兩個CGRect,CGRect A和CGRect B.我的UIView的框架與CGRect B相同,但是我想創建一個動畫,顯示UIView從框架A轉換到B的框架。有沒有辦法計算將幀A轉換爲幀B所需的CGAffineTransform?

我正在嘗試通過改變UIView的transform屬性來做到這一點,所以我不必太在意它的框架。但是,我需要CGAffineTransform來實現這一點。什麼是計算這種變換的最好方法?

+0

是否有任何迫切的理由不簡單地將CGRect A的框架屬性動畫到CGRect B? –

+1

未按下。但原因是保持視圖的框架是靜態的並且使用變換來移動它顯着簡化了在更復雜的狀態變化(例如自動旋轉)期間跟蹤它。 – SpacyRicochet

+0

有趣的方法。 +1 :) –

回答

7

我一直沒有找到任何方便的方法,所以我採取了嘗試和真正的矩陣計算來實現這一點。

給定一個的CGRect A和的CGRect B,計算從A到去乙所需的轉化,進行以下操作:

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

在上面的代碼段中的最後一行,需要如下改變:

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

26

以前的答案並沒有爲我工作。這應該工作:

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

斯威夫特:

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

我見過的最好的片段之一。做得好 – YichenBman

3

這裏有josema.vitaminew answer的變化也考慮縱橫比(有用的,如果您使用的視頻或圖像時):

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

一不錯的斯威夫特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) 
    } 
} 
相關問題