Вы применили перспективу на слое суперпредставления, и это то, что вы получаете.Если вам нужна перспектива, основанная на отдельных подуровнях (без учета общей перспективы), то вы должны применять перспективу к ним индивидуально.Например:
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
всегда будут возвращать старое значение, а не текущее значение.Это также усложняет ситуацию, если вы применяете дополнительную анимацию к этому слою.Вот почему по умолчанию удаляется анимация после завершения.