代码之家  ›  专栏  ›  技术社区  ›  Sweeper

如何围绕中心旋转CGRect?

  •  0
  • Sweeper  · 技术社区  · 6 年前

    背景:

    我想展示一个顺时针旋转90度的标签。旋转的标签应该在我指定的某个框架中。比如说(10,100,50,100)。

    我知道我可以通过使用 CGAffineTransform . 我也知道我不应该 frame 根据 docs .

    如果此属性的值不是identity转换,则frame属性中的值未定义,应忽略。

    我试图在转换后设置框架,虽然它起作用,但我不想做医生告诉我不要做的事情。

    label2.transform = CGAffineTransform(rotationAngle: -.pi / 2)
    label2.frame =  CGRect(x: 10, y: 100, width: 50, height: 100)
    

    然后我想,我可以这么做:

    1. 创建 CGRect 我想要的框架
    2. 逆时针旋转90度
    3. 将该矩形设置为标签的框架
    4. 顺时针旋转标签90度

    然后标签会在所需的框架中。

    所以我试着这样做:

        let desiredFrame = CGRect(x: 10, y: 100, width: 50, height: 100) // step 1
        // I am using UIViews here because I am just looking at their frames
        // whether it is a UIView or UILabel does not matter
        // label1 is a view that is in the desired frame but not rotated
        // If label2 has the correct frame, it should completely cover label1
        let label1 = UIView(frame: desiredFrame)
        let label2Frame = rotateRect(label1.frame) // step 2
        let label2 = UIView(frame: label2Frame) // step 3
        view.addSubview(label1)
        view.addSubview(label2)
        label1.backgroundColor = .red
        label2.backgroundColor = .blue
        label2.transform = CGAffineTransform(rotationAngle: -.pi / 2) // step 4
    

    在哪里? rotateRect 声明如下:

    func rotateRect(_ rect: CGRect) -> CGRect {
        return rect.applying(CGAffineTransform(rotationAngle: .pi / 2))
    }
    

    这没用。 label2 不重叠 label1 完全。我都看不见 标签2 在屏幕上。

    我怀疑这是因为 applying 方法 CGRect公司 围绕原点旋转矩形,而不是矩形的中心。所以我试着先把矩形变换到原点,旋转它,然后再变换回来,如下所示 post 关于数学,她说:

    func rotateRect(_ rect: CGRect) -> CGRect {
        let x = rect.x
        let y = rect.y
        let transform = CGAffineTransform(translationX: -x, y: -y)
                            .rotated(by: .pi / 2)
                            .translatedBy(x: x, y: y)
        return rect.applying(transform)
    }
    

    但是,我还是看不见 标签2 在屏幕上。

    0 回复  |  直到 6 年前
        1
  •  1
  •   Sandeep    6 年前

    我认为你的转换顺序是不正确的。如果你这么做,

    平移(x,y)*Rotate()*平移(-x,-y)

    把它和你的 rotateRect 似乎工作正常。因为,您将视图旋转90度,蓝色视图将完全阻挡红色视图。用其他角度试试,你会看到效果更突出。

    func rotateRect(_ rect: CGRect) -> CGRect {
        let x = rect.midX
        let y = rect.midY
        let transform = CGAffineTransform(translationX: x, y: y)
                                        .rotated(by: .pi / 2)
                                        .translatedBy(x: -x, y: -y)
        return rect.applying(transform)
    }
    
        2
  •  0
  •   Sweeper    6 年前

    因为我只想将视图旋转90度,所以初始帧的宽度和高度将与旋转帧的宽度和高度相反。

    初始帧和旋转帧的中心是相同的,因此我们可以设置 center 在转换之前将标签放置在所需框架的中心。

        let desiredFrame = CGRect(x: 10, y: 100, width: 50, height: 100)
        let label1 = UIView(frame: desiredFrame)
        // get the centre of the desired frame
        // this is also equal to label1.center
        let center = CGPoint(x: desiredFrame.midX, y: desiredFrame.midY)
        let label2Frame = CGRect(x: 0, y: 0, width: desiredFrame.height, height: desiredFrame.width)
        let label2 = UIView(frame: label2Frame)
        view.addSubview(label1)
        view.addSubview(label2)
        label1.backgroundColor = .red
        label2.backgroundColor = .blue
        label2.center = center // set the centre of label2 before the transform
        label2.transform = CGAffineTransform(rotationAngle: -.pi / 2)