Как повернуть CGRect вокруг его центра? - PullRequest
0 голосов
/ 02 марта 2019

Фон:

Я хочу показать метку, которая повернута на 90 градусов по часовой стрелке.Повернутая метка должна быть в определенной рамке, которую я указываю.Допустим, (10, 100, 50, 100).

Я знаю, что могу вращать вид с помощью CGAffineTransform.Я также знаю, что не следует устанавливать свойство frame после завершения преобразования, согласно docs .

Когда значение этого свойства отличается отпреобразование идентичности, значение в свойстве 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 вообще.Я даже не вижу 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 на экране.

Ответы [ 2 ]

0 голосов
/ 02 марта 2019

Поскольку я хочу повернуть вид только на 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)
0 голосов
/ 02 марта 2019

Я думаю, что порядок ваших преобразований неверен.Если вы сделаете это так, то,

Перевести (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)
}
...