iOS 3DAnimations: проблемы при повороте нескольких наложенных видов

#ios #animation #3d #rotation #caanimation

#iOS #Анимация #3D #вращение #caanimation

Вопрос:

Проблема

При одновременном переключении видов (например, поворот числа пи) на одной оси иерархия видов (какой из них спереди, а какой сзади), по-видимому, нарушается.

Подробные объяснения

На приведенном ниже GIF-изображении серый вид со значком swift находится спереди, а синий вид сзади.

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

С синим цветом supView

Теперь, повторяя точно такую же анимацию, к синему виду теперь не применяются цвета, но он все еще находится в иерархии видов за серым видом и все еще анимирован.

нет цветного представления

Желаемый результат

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