Как перевернуть CALayer вокруг оси Y?

Я использую этот код внутри подкласса CALayer, экземпляры которого являются подслоями корневого CALayer.

-(void)setSelected:(bool)s {
    selected=s;
    if (s)
    {
        CATransform3D  rot = CATransform3DMakeRotation(M_PI, 0, 1, 0);
        rot.m34=-1.0 / 200;
        [self setTransform:rot];

    }
    else
    {
            CATransform3D  rot = CATransform3DMakeRotation(0, 0, 1, 0);
        rot.m34=-1.0 / 200;
        [self setTransform:rot];
    }
}

Когда для выбранного свойства установлено значение TRUE, происходит вот что: поворот выполняется до тех пор, пока угол не станет равным M_PI/2, затем слой исчезает, поскольку он ортогонален. Конец анимации неправильный: край, который, казалось, рос в первой части анимации (например, с левой стороны), заканчивает анимацию с левой стороны, а не с правой. Однако содержимое перевернуто.

Я думаю, что это как-то связано с интерполяцией между двумя матрицами вращения, но я не могу точно понять, что происходит.

Детали: анимация выглядит следующим образом:

  1. увеличить вращение вокруг оси Y на +Pi/2
  2. перелистывание контента
  3. увеличить вращение вокруг оси Y на -Pi/2, как если бы он отскочил от плоскости (yz)

Перевернутый контент - это то, чего я пытаюсь достичь.

Вот кадры анимации, которые я получаю. Как видите, меньшая сторона трапеции всегда слева; он должен быть справа в конце анимации (верхний правый кадр). Слой, вращающийся вокруг оси Y


person alecail    schedule 25.09.2012    source источник
comment
В чем проблема? Это то, что содержимое перевернуто, или это угол, или это направление переворота?   -  person David Rönnqvist    schedule 25.09.2012


Ответы (3)


Математика вашего преобразования неверна. Вы должны применить преобразование перспективы после преобразования вращения, что означает объединение обоих преобразований. Изменение коэффициента m34 вашего преобразования вращения не эквивалентно.

Вы должны заменить свой код следующим:

-(void)setSelected:(bool)s {
    selected=s;
    CATransform3D perpectiveTransform = CATransform3DIdentity;
    perpectiveTransform.m34 =-1.0 / 200;

    if (s)
    {

        CATransform3D  rot = CATransform3DMakeRotation(M_PI, 0, 1, 0);
        [self setTransform:CATransform3DConcat(rot, perpectiveTransform)];

    }
    else
    {
        CATransform3D  rot = CATransform3DMakeRotation(0, 0, 1, 0);
        [self setTransform:CATransform3DConcat(rot, perpectiveTransform)];
    }
}

Между прочим, более удобный метод применения перспективных преобразований — использовать свойство суперслоя sublayerTransform, таким образом применяя его к каждому подслою (если это необходимо).

Это даст что-то вроде:

self.superlayer.sublayerTransform = perspectiveTransform;  //do this in your setup
....
self.transform = rot;

для идентично выглядящего результата.

person amadour    schedule 26.09.2012
comment
Второй способ тоже возможен, но в моем случае он не работает, потому что я просто хотел, чтобы каждый слой выполнял трехмерное вращение в своем собственном пространстве, чтобы оно выглядело точно так же (без искажений из-за положения в пространстве). У меня есть резинка для выбора этих слоев, которая также является CALayer. Установка такого преобразования также преобразует резиновую ленту, и расположение щелчков мыши внутри представления также должно быть непроецировано, если я хочу использовать их для рисования резиновой ленты выделения. - person alecail; 26.09.2012

Если кто-то просто хочет перевернуть изображение или направление просмотра по горизонтали

yourView.layer.transform = CATransform3DMakeScale(-1, 1, 1);

or

yourView.layer.affineTransform =  CGAffineTransformMakeScale(-1, 1);
person Ted    schedule 10.09.2015

Представьте, что ваш слой — это кусок плоского полупрозрачного пластика, на который проецируется изображение, поэтому оно светится с обеих сторон. При вращении pi/2 он находится на ребре и поэтому исчезает. Когда ваше вращение становится больше, чем пи/2, но меньше, чем пи, обратная сторона плоского листа пластика обнажается. Поскольку он полупрозрачный, вы видите обратную сторону изображения, но поскольку вы видите его сзади, оно зеркальное. Когда угол достигает числа пи, лист переворачивается на полные 180 градусов по оси у. Она перевернута, и вы можете видеть изображение сзади, так что она перевернута.

person Duncan C    schedule 26.09.2012