ios - 变换旋转后如何找到UIView的框架

标签 ios swift uiview uiimageview cgaffinetransform

我有一个非常简单的 UIImageView,它包含在容器 View 中。它们大小相同,没有使用自动布局。当用户按下按钮时,UIImageView 应该旋转 90 度。当 UIImageView(不是 UIImageView.image)旋转时,它应该适合其父 View (.ScaleAspectFit)。 到目前为止,我已经找到了最简单的部分:变换旋转。

    self.currentRotation += 90
    if self.currentRotation >= 360 {
        self.currentRotation = 0
    }

    let angleInRadians: Double
    switch self.currentRotation {
    case 0:
        angleInRadians = 0
    case 90:
        angleInRadians = M_PI_2
    case 180:
        angleInRadians = M_PI
    case 270:
        angleInRadians = M_PI + M_PI_2
    default:
        angleInRadians = 0
        break;
    }
    let newTransform = CGAffineTransformRotate(CGAffineTransformIdentity, CGFloat(angleInRadians))

通过从 this question 获取一些信息,我能够编写 Swift 版本的辅助扩展,但我仍然不知道如何找到 UIImageView 的框架。

extension UIView {
    var originalFrame: CGRect {
        let currentTransform = self.transform
        self.transform = CGAffineTransformIdentity
        let originalFrame = self.frame
        self.transform = currentTransform
        return originalFrame
    }

    var transformedTopLeftPoint: CGPoint {
        return self.transformedPointForOriginalPoint(originalFrame.topLeftPoint)
    }

    var transformedTopRightPoint: CGPoint {
        return self.transformedPointForOriginalPoint(originalFrame.topRightPoint)
    }

    var transformedBottomLeftPoint: CGPoint {
        return self.transformedPointForOriginalPoint(originalFrame.bottomLeftPoint)
    }

    var transformedBottomRightPoint: CGPoint {
        return self.transformedPointForOriginalPoint(originalFrame.bottomRightPoint)
    }

    // helper to get point offset from center
    func centerOffset(point: CGPoint) -> CGPoint {
        return CGPoint(x: point.x - self.center.x, y: point.y - self.center.y)
    }

    // helper to get point back relative to center
    func pointRelativeToCenter(point: CGPoint) -> CGPoint {
        return CGPoint(x: point.x + self.center.x, y: point.y + self.center.y)
    }

    // helper to get point relative to transformed coords
    func transformedPointForOriginalPoint(point: CGPoint) -> CGPoint {
        // get offset from center
        let offset = self.centerOffset(point)
        // get transformed point
        let transformedPoint = CGPointApplyAffineTransform(offset, self.transform)
        // make relative to center
        return self.pointRelativeToCenter(transformedPoint)
    }
}

extension CGRect {
    var topLeftPoint: CGPoint {
        return self.origin
    }

    var topRightPoint: CGPoint {
        return CGPoint(x: self.origin.x + self.size.width, y: self.origin.y)
    }

    var bottomLeftPoint: CGPoint {
        return CGPoint(x: self.origin.x, y: self.origin.y + self.size.height)
    }

    var bottomRightPoint: CGPoint {
        return CGPoint(x: self.origin.x + self.size.width, y: self.origin.y + self.size.height)
    }
}

为了更好地说明,我附上了一张图片。

image for better understanding

It shows a rotated view on top of its original frame (the smallest of the outlines) and the updated frame (the largest gray outline). The circles indicate the view's top-right corner before and after rotation. After the transform is applied, the frame updates to the minimum bounding box that encloses the view. Its new origin (the top-left corner of the gray outside box) has essentially nothing to do with the original view origin (the top-left corner of the black unrotated inner box). iOS does not provide a way to retrieve that adjusted point. Here are a series of view methods that perform that math for you. (UIView extension above)

我需要找到灰色框的框架。但即使使用这些方法,我仍然无法弄清楚该怎么做。实现我想要的结果的公式/算法是什么?

最佳答案

转换后 View 的 center 保持不变。所以你需要根据中心来计算东西。像这样:

func originalFrame() -> CGRect {
    CGAffineTransform currentTransform = self.transform;
    self.transform = CGAffineTransformIdentity;
    let originalFrame = self.frame;
    self.transform = currentTransform;

    return originalFrame;
}

func centerOffset(point:CGPoint) -> CGPoint {
    return CGPointMake(point.x - self.center.x, point.y - self.center.y);
}

func pointRelativeToCenter(point:CGPoint) -> CGPoint {
    CGPointMake(point.x + self.center.x, point.y + self.center.y);
}


func newPointInView(point:CGPoint) -> CGPoint {
    let offset = self.centerOffset(point)
    let transformedPoint = CGPointApplyAffineTransform(offset, self.transform);
    return self.pointRelativeToCenter(transformedPoint)
}

func newTopLeft() -> CGPoint {
    let frame = self.originalFrame()
    return self.newPointInView(frame)
}

func newTopRight() -> CGPoint {
    let frame = self.originalFrame()
    var point = frame.origin
    point.x = point.x + frame.size.width
    return self.newPointInView(point)
}


func newBottomLeft() -> CGPoint {
    let frame = self.originalFrame()
    var point = frame.origin
    point.y = point.y + frame.size.height
    return self.newPointInView(point)
}


func newBottomRight() -> CGPoint {
    let frame = self.originalFrame()
    var point = frame.origin
    point.x = point.x + frame.size.width
    point.y = point.y + frame.size.height
    return self.newPointInView(point)
}

引用这个SO Thread了解更多详情。

关于ios - 变换旋转后如何找到UIView的框架,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33477247/

相关文章:

ios - iOS 8 SDK 中的 GL_DRAW_FRAMEBUFFER_APPLE 和 GL_READ_FRAMEBUFFER_APPLE 在哪里?

ios - 从 UIViewController 中删除我的自定义 MKMapView

ios - 从其他类访问结构

ios - 在 UIKit View 层次结构中感到困惑

ios - UIView 蒙版透明。

iphone - UIView 在 UITableViewController 的中心

ios - ARC双向关系

ios - 线程 1 : signal SIGABRT (Tried prev solutions)

ios - 是否有 iOS API 可以识别您的哪些联系人可能是其他 iOS 用户?

swift 4.2 如何正确检查已用时间