#ios #animation #3d #rotation #caanimation
#iOS #Анимация #3D #вращение #caanimation
Вопрос:
Проблема
При одновременном переключении видов (например, поворот числа пи) на одной оси иерархия видов (какой из них спереди, а какой сзади), по-видимому, нарушается.
Подробные объяснения
На приведенном ниже GIF-изображении серый вид со значком swift находится спереди, а синий вид сзади.
Вы можете заметить, что когда первый поворот серого вида достигает pi / 2, его прозрачность, кажется, изменяется. Кроме того, когда серый завершает свой первый поворот, вместо того, чтобы оставаться за синим видом, он оказывается впереди во время всего следующего поворота.
Теперь, повторяя точно такую же анимацию, к синему виду теперь не применяются цвета, но он все еще находится в иерархии видов за серым видом и все еще анимирован.
Желаемый результат
Я пытаюсь добиться такой же анимации, сохраняя синий вид поверх серого вида, без какого-либо видимого изменения прозрачности в сером виде. Я использую UIViewPropertyAnimator
, чтобы позже иметь возможность очистить анимацию.
Код
Следующий код описывает упрощенный метод flip (как расширение UIView), на котором основана анимация.
extension UIView{
func flipping(_ times: Int = 1, to direction: FoldingDirection, within duration: Double = 0.01, startAfter delay: Double = 0) {
guard times > 0 else { return }
// resets the layer anchor point depending on the current transform states of the view (calling a specific method)
self.setAnchorPoint(at: direction.anchor())
// adding perspective effect
self.layer.transform.m34 = 1 / 250
// setting rotation axis
let axis: CGPoint = {
switch direction {
case .right, .left:
return CGPoint(x: 1, y: 0)
default:
return CGPoint(x: 0, y: 1)
}
}()
let flipDuration = duration > 0 ? duration / Double(times) : 0.01
// creating animator
let animator = UIViewPropertyAnimator(duration: flipDuration, curve: .linear) {
self.layer.transform = CATransform3DRotate(self.layer.transform, .pi, axis.y, axis.x, 0)
}
animator.startAnimation(afterDelay: delay)
animator.addCompletion { (position) in
if position == .end {
self.flipping(times - 1, to: direction, within: duration * ( 1 - 1 / Double(times)), startAfter: 0)
}
}
}
}
Вызов анимации:
greyView.flipping(3, to: .right, within: 9, startAfter: 0)
blueView.flipping(2, to: .right, within: 6, startAfter: 3)
Спасибо за вашу помощь!
РЕДАКТИРОВАТЬ После выполнения нескольких тестов кажется, что иерархия представлений действительно изменилась во время анимации: вращение, похоже, происходит за плоскостью просмотра.
Ответ №1:
В такого рода анимациях их Zposition не назначается, так что вы не можете контролировать, какая из них ближе, а другая дальше.
Назначение zPosition слоям во время события устранит ваши проблемы. Вы можете сравнить
greyView.layer.zPosition = 20
blueView.layer.zPosition = -20
и
greyView.layer.zPosition = 200
blueView.layer.zPosition = -200
и вы поймете, что я имею в виду.
Комментарии:
1. Ты снова опередил меня! 🙂 Обнаружил, что копался в документах разработчика 3D Apple. Вам необходимо установить его перед вызовом метода. Спасибо @E.Coms! Еще один, который вы правильно поняли :))))