有没有办法计算将视图从 A 帧转换为帧 B 所需的 CGAffineTransform



比如说,我有两个CGRects,CGRect A和CGRect B。我的 UIView 的帧与 CGRect B 相同,但我想创建一个动画,显示 UIView 从 A 帧过渡到 B 帧。

我正在尝试通过更改 UIView 的 transform 属性来做到这一点,所以我不必过多地弄乱它的框架。但是,我需要CGAffineTransform来实现这一点。计算此转换的最佳方法是什么?

以前的答案对我不起作用。这应该有效:

斯威夫特 5(扩展)

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

斯威夫特 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)
}

迅速

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

目标-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;
}
我无法

为此找到任何方便的方法,因此我求助于久经考验的真实矩阵计算来实现这一点。

给定 CGRect A 和 CGRect B,要计算从 A 到 B 所需的转换,请执行以下操作:

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

以下是josema.vitaminew答案的变体,它也考虑了纵横比(如果您正在处理视频或图像,则很有用):

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

一个不错的 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)
    }
}

上述代码片段中的最后一行需要更改如下:

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

我开始使用Kanobius的答案,但要么我误解了他对术语"纵横比"的使用,要么他误解了,因为它没有像我预期的那样执行。 这是我的版本,它保持原始视图的纵横比(通过将缩放应用于 H 和 W)以实现"宽高比拟合"行为

+ (CGAffineTransform)transformFromRect:(CGRect)sourceRect toRect:(CGRect)finalRect keepingAspectRatio:(BOOL)keepingAspectRatio
{
    CGAffineTransform transform = CGAffineTransformIdentity;
    // since the scale transform works around the midpoints, align them before doing the transform.
    transform = CGAffineTransformTranslate(transform, -(CGRectGetMidX(sourceRect)-CGRectGetMidX(finalRect)), -(CGRectGetMidY(sourceRect)-CGRectGetMidY(finalRect)));
    CGFloat originalHeight = sourceRect.size.height;
    CGFloat scaledHeight = finalRect.size.height;
    CGFloat hScalePercentage = scaledHeight / originalHeight;
    CGFloat originalWidth = sourceRect.size.width;
    CGFloat scaledWidth = finalRect.size.width;
    CGFloat wScalePercentage = scaledWidth / originalWidth;
    if (keepingAspectRatio)  
    {
        CGFloat scalePercentage = MIN(hScalePercentage, wScalePercentage);   // the most amount of scaling == smallest float number
        transform =  CGAffineTransformScale(transform, scalePercentage, scalePercentage);
    }
    else
    {
        transform = CGAffineTransformScale(transform, wScalePercentage, hScalePercentage);
    }
    return transform;
}

相关内容

  • 没有找到相关文章

最新更新