Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to calculate the CGAffineTransform needed to transform a view from frame A to frame B?

Say, I have two CGRects, CGRect A and CGRect B. My UIView's frame is the same as CGRect B, but I want to create an animation showing the UIView transitioning from frame A to B.

I'm trying to do this by changing the transform property of the UIView, so I don't have to mess around with its frame too much. However, I need the CGAffineTransform to make this possible. What is the best way to calculate this transform?

like image 607
SpacyRicochet Avatar asked May 23 '12 13:05

SpacyRicochet


2 Answers

The previous answers didn't work for me. This should work:

Swift 5 (extension)

extension CGAffineTransform {
    init(from source: CGRect, to destination: CGRect) {
        let t = CGAffineTransform.identity
            .translatedBy(x: destination.midX - source.midX, y: destination.midY - source.midY)
            .scaledBy(x: destination.width / source.width, y: destination.height / source.height)
        self.init(a: t.a, b: t.b, c: t.c, d: t.d, tx: t.tx, ty: t.ty)
    }
}

Swift 4

func transformFromRect(from source: CGRect, toRect destination: CGRect) -> CGAffineTransform {
    return CGAffineTransform.identity
        .translatedBy(x: destination.midX - source.midX, y: destination.midY - source.midY)
        .scaledBy(x: destination.width / source.width, y: destination.height / source.height)
}

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

Objective-C

+ (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;
}
like image 163
José Manuel Sánchez Avatar answered Sep 21 '22 04:09

José Manuel Sánchez


I haven't been able to find a convenience method of any kind for this, so I resorted to tried and true matrix calculations to achieve this.

Given a CGRect A and CGRect B, to calculate the transformation needed to go from A to B, do the following:

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);
like image 20
SpacyRicochet Avatar answered Sep 21 '22 04:09

SpacyRicochet