Онлайн курсы по Swift

Анимация — это отличный способ показать функциональность наших приложений посредством движения и порадовать наших пользователей. Добавление анимации в нужные места может сделать интерфейс вашего приложения более привлекательным и приятным.

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

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

Основы

SpriteKit — это встроенная среда Apple (начиная с iOS 7) для разработки 2D игр. Это также очень хороший инструмент для любых 2D-чертежей и анимаций.

SpriteKit может быть очень полезным при создании более сложных, автономных сцен.

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

 

Настройка сцены

Все содержимое SpriteKit представлено в сцене, управляемой экземпляром класса SKScene. Контент затем определяется с использованием системы на основе узлов, которая позволяет создавать иерархии, как при использовании UIViews или CALayers.

Вы создаете узлы, используя различные подклассы SKNode, например, SKSpriteNode для контента на основе спрайтов (изображений) или SKLabelNode для текстового контента.

Наконец, вы используете действия (представленные классом SKAction), чтобы ваши узлы выполняли различные анимации (например, перемещение, масштабирование, поворот и т.д.) в вашей сцене.

Итак начнем

Начнем с создания контейнера SKScene для нашей анимации. Мы зададим квадратный размер, взятый из минимального размера представления ViewController’a, и установим белый цвет фона:

 

extension AnimationViewController {
    func makeScene() -> SKScene {
        let minimumDimension = min(view.frame.width, view.frame.height)
        let size = CGSize(width: minimumDimension, height: minimumDimension)

        let scene = SKScene(size: size)
        scene.backgroundColor = .white
        return scene
    }
}

 

Вы представляете SKScene, используя SKView (которое является подклассом UIView на iOS). Мы добавим такой вид в наш контроллер просмотра и зададим его размер и центральную точку. Наконец, мы расскажем, как представить нашу сцену следующим образом:

 

class AnimationViewController: UIViewController {
    private lazy var animationView = SKView()

    override func loadView() {
        super.loadView()
        view.addSubview(animationView)
    }

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)

        guard animationView.scene == nil else {
            return
        }

        let scene = makeScene()
        animationView.frame.size = scene.size
        animationView.presentScene(scene)
    }

    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()

        animationView.center.x = view.bounds.midX
        animationView.center.y = view.bounds.midY
    }
}

Добавление узлов

Итак, теперь у нас есть сцена для рендеринга. Давайте начнем добавлять некоторые материалы. Если вы делаете рендеринг изображений и анимаций с использованием ключевых кадров, вы можете использовать SKSpriteNode для рендеринга. Но в этом примере мы будем придерживаться простых эмодзи, поэтому мы будем использовать SKLabelNode (что в SpriteKit эквивалентно UILabel).

Начнем с создания расширения SKLabelNode, которое позволяет нам отображать эмодзи:

 

extension SKLabelNode {
    func renderEmoji(_ emoji: Character) {
        fontSize = 50
        text = String(emoji)

        verticalAlignmentMode = .center
        horizontalAlignmentMode = .center
    }
}

 

Затем мы создаем еще один метод расширения на нашем контроллере просмотра, чтобы добавить всю сцену в нашу сцену:

На некоторых браузерах могут не отображаться эмодзи в этой части кода: [«?«, «?«, «?«, «?«;]

 

extension AnimationViewController {
    func addEmoji(to scene: SKScene) {
        let allEmoji: [Character] = ["?", "?", "?", "?";]
        let distance = floor(scene.size.width / 4)

        for (index, emoji) in allEmoji.enumerated() {
            let node = SKLabelNode()
            node.renderEmoji(emoji)
            node.position.y = floor(scene.size.height / 2)
            node.position.x = distance * (CGFloat(index) + 0.5)
            scene.addChild(node)
        }
    }
}

Давайте анимировать!

Давайте перейдем к следующей интересной части — создадим нашу анимацию. Каждый символ эмодзи будет увеличиваться, а затем уменьшаться, с небольшой задержкой:

 

func animateNodes(_ nodes: [SKNode]) {
        for (index, node) in nodes.enumerated() {
            let delayAction = SKAction.wait(forDuration: TimeInterval(index) * 0.2)

            let scaleUpAction = SKAction.scale(to: 1.5, duration: 0.3)
            let scaleDownAction = SKAction.scale(to: 1, duration: 0.3)

            let waitAction = SKAction.wait(forDuration: 2)

            let scaleActionSequence = SKAction.sequence([scaleUpAction, scaleDownAction, waitAction])

            let repeatAction = SKAction.repeatForever(scaleActionSequence)

            let actionSequence = SKAction.sequence([delayAction, repeatAction])

            node.run(actionSequence)
        }
    }

 

Вышеприведенный код работает, но его трудно читать, особенно если мы уберем комментарии. Но мы можем легко это исправить! Благодаря удивительному синтаксису точечной нотации Swift, мы можем значительно уменьшить многословие нашего кода и избавиться от всех временных let назначений:

 

extension AnimationViewController {
    func animateNodes(_ nodes: [SKNode]) {
        for (index, node) in nodes.enumerated() {
            node.run(.sequence([
                .wait(forDuration: TimeInterval(index) * 0.2),
                .repeatForever(.sequence([
                    .scale(to: 1.5, duration: 0.3),
                    .scale(to: 1, duration: 0.3),
                    .wait(forDuration: 2)
                ]))
            ]))
        }
    }
}

 

Теперь мы можем создать анимацию, вызвав вышеупомянутый метод со всеми узлами нашей сцены makeScene():

 

animateNodes(scene.children)

Закрутим эмодзи

Теперь, когда у нас есть легко читаемый код анимации, мы можем начать с ним играть. Предположим, мы хотели добавить немного завихрения (в буквальном смысле!) к нашей анимации, вращая наши эмодзи на 360 градусов одновременно с масштабированием вверх и вниз.

Все, что мы должны сделать, чтобы это произошло — объединить действия масштабирования и действия вращения в группу, например:

 

extension AnimationViewController {
    func animateNodes(_ nodes: [SKNode]) {
        for (index, node) in nodes.enumerated() {
            node.run(.sequence([
                .wait(forDuration: TimeInterval(index) * 0.2),
                .repeatForever(.sequence([
                    .group([
                        .sequence([
                            .scale(to: 1.5, duration: 0.3),
                            .scale(to: 1, duration: 0.3)
                        ]),
                        .rotate(byAngle: .pi * 2, duration: 0.6)
                    ]),
                    .wait(forDuration: 2)
                ]))
            ]))
        }
    }
}

 

Это даст нам следующий результат:

 

Вывод

Как вы можете видеть в приведенном выше примере, использование SpriteKit для анимаций позволяет нам писать очень декларативный код анимации, который легко изменить, расширить и поэкспериментировать.

Спасибо за прочтение! ?

Пролистать наверх