背景:
我想要显示一个顺时针旋转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)
然后我想,我能做到这一点:
CGRect
然后标签将在所需的框架中。
所以我尝试过这样的事情:
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
。
我认为你的转换顺序不正确。如果你这样做,那,
翻译(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)
}
由于我只想将视图旋转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)