如何旋转CGRect的中心?

问题描述 投票:0回答:2

背景:

我想要显示一个顺时针旋转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. 将rect设置为标签的框架
  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重叠。我甚至无法在屏幕上看到label2

我怀疑这是因为applying中的CGRect方法围绕原点旋转矩形,而不是矩形的中心。所以我试着先将矩形转换为原点,旋转它,然后将其转换回来,因为这个post在math.SE上说:

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

但是,我仍然无法在屏幕上看到label2

ios swift cgaffinetransform cgrect
2个回答
1
投票

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

翻译(x,y)*旋转(θ)*翻译(-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)
}

0
投票

由于我只想将视图旋转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)
© www.soinside.com 2019 - 2024. All rights reserved.