Странная перспектива с CATransform3DMakeRotation - PullRequest
2 голосов
/ 27 ноября 2011

У меня странная проблема с CATransform3DMakeRotation.Когда повернутый вид находится в центре суперпредставления, он выглядит следующим образом:

Действительный XHTML http://i1183.photobucket.com/albums/x467/Laurin_Koppenwallner/Bildschirmfoto2011-11-27um181544.png

Вот как это должно выглядеть.Однако, когда он находится где-то еще в суперпредставлении, скажем, в левом нижнем углу, он выглядит следующим образом:

Допустимый XHTML http://i1183.photobucket.com/albums/x467/Laurin_Koppenwallner/Bildschirmfoto2011-11-27um181627.png

Обратите внимание, что он наклонен вправо.То же самое происходит, когда он находится в правом нижнем углу, только когда он наклоняется влево.Есть ли способ заставить его наклоняться так, как он должен все время и в каждой позиции?Код для достижения этого преобразования выглядит следующим образом:

    CALayer *layer = view.layer;

    CATransform3D aTransform = CATransform3DIdentity;
    float zDistance = 1000;
    aTransform.m34 = 1.0 / -zDistance;  

    self.view.layer.sublayerTransform = aTransform;


    CABasicAnimation *rotateAnim = [CABasicAnimation animationWithKeyPath:@"transform"];
    rotateAnim.fromValue= [NSValue valueWithCATransform3D:CATransform3DMakeRotation(0, 0, 0, 0)];
    rotateAnim.duration=0.12;
    rotateAnim.toValue=[NSValue valueWithCATransform3D:CATransform3DMakeRotation(20*M_PI/180, 1, 0, 0)];

    rotateAnim.removedOnCompletion = NO;
    rotateAnim.fillMode = kCAFillModeForwards;
    [layer addAnimation:rotateAnim forKey:@"rotateAnim"];

1 Ответ

3 голосов
/ 27 ноября 2011

Вы применили перспективу на слое суперпредставления, и это то, что вы получаете.Если вам нужна перспектива, основанная на отдельных подуровнях (без учета общей перспективы), то вы должны применять перспективу к ним индивидуально.Например:

CALayer *layer = view.layer;

CATransform3D aTransform = CATransform3DIdentity;
CGFloat zDistance = 2000.;
aTransform.m34 = 1.0 / -zDistance;  

CABasicAnimation *rotateAnim = [CABasicAnimation animationWithKeyPath:@"transform"];

rotateAnim.fromValue= [NSValue valueWithCATransform3D:aTransform];
aTransform = CATransform3DRotate(aTransform, 20*M_PI/180, 1, 0, 0);;
rotateAnim.duration=0.12;
rotateAnim.toValue=[NSValue valueWithCATransform3D:aTransform];
layer.transform = aTransform;

[layer addAnimation:rotateAnim forKey:@"rotateAnim"];

В этом примере я применяю перспективу (m34) как в fromValue, так и в toValue слоя.Это дает вам перспективу относительно наблюдателя, стоящего перед самим слоем.Ваш исходный код содержал наблюдателя, стоящего перед центром обзора, и поэтому вы получаете некоторую перекос перспективы.

Я внес некоторые другие небольшие изменения здесь.Обычно я ставлю наблюдателя на 2000, а не на 1000. Я нахожу, что перспектива на 1000 часто больше, чем хотелось бы (если только вы не стремитесь к сильной перспективе).В зависимости от вашей проблемы, вы можете полностью избавиться от перспективы.Не применяйте это просто по привычке.

Что еще более важно, я изменил, как вы применяли анимацию в конце.Использование removedOnCompletion=NO и kCAFillModeForwards делает вещи намного более сложными, чем просто применение анимации к модели (layer.transform=aTransform) и нормальное удаление анимации.В частности, использование removedOnCompletion=NO означает, что последующие запросы на layer.transform всегда будут возвращать старое значение, а не текущее значение.Это также усложняет ситуацию, если вы применяете дополнительную анимацию к этому слою.Вот почему по умолчанию удаляется анимация после завершения.

...