О чем этот пример

Иногда в игре требуется вывести сложный UI-компонент, который проще создать на HTML и CSS, чем на канвасе. Phaser 3 позволяет встраивать и анимировать обычные DOM-элементы прямо на игровую сцену, сохраняя все возможности CSS. В этой статье разберем, как создать DOM-узел, позиционировать его относительно игровых координат и применять к нему плавную анимацию с помощью твинов, как к любому другому игровому объекту.

Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.

Живой запуск

Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.

Исходный код


class Example extends Phaser.Scene
{
    preload ()
    {
        this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
        this.load.image('einstein', 'assets/pics/ra-einstein.png');
    }

    create ()
    {
        const element = this.add.dom(400, 300, 'div', 'background-color: rgba(255, 255, 0, 0.5); width: 300px; height: 200px; font: 48px Arial; font-weight: bold', 'Phaser 3');

        const marker = this.add.rectangle(400, 300, 16, 16, 0xff00ff);

        this.tweens.add({
            targets: element,
            duration: 3000,
            angle: 360,
            scaleX: 2,
            scaleY: 2,
            ease: 'Sine.easeInOut',
            loop: -1,
            yoyo: true
        });
    }
}

const config = {
    type: Phaser.AUTO,
    scale: {
        _mode: Phaser.Scale.FIT,
        parent: 'phaser-example',
        width: 800,
        height: 600
    },
    dom: {
        createContainer: true
    },
    scene: Example
};

const game = new Phaser.Game(config);

Настройка проекта для работы с DOM

Чтобы использовать DOM-элементы в Phaser, необходимо включить соответствующую опцию в конфигурации игры. Без этого система DOM-объектов не будет инициализирована.

const config = {
    type: Phaser.AUTO,
    scale: {
        _mode: Phaser.Scale.FIT,
        parent: 'phaser-example',
        width: 800,
        height: 600
    },
    dom: {
        createContainer: true
    },
    scene: Example
};

Ключевой параметр здесь – dom.createContainer: true. Он указывает Phaser создать специальный контейнер в DOM-дереве страницы, куда будут добавляться все элементы, созданные через this.add.dom. Без этого контейнера метод add.dom не будет работать.

Создание DOM-элемента на сцене

DOM-элемент создается методом this.add.dom. Он принимает координаты (x, y), имя тега, строку стилей и необязательный текстовый контент. Элемент позиционируется абсолютно внутри игрового холста.

create ()
{
    const element = this.add.dom(400, 300, 'div', 'background-color: rgba(255, 255, 0, 0.5); width: 300px; height: 200px; font: 48px Arial; font-weight: bold', 'Phaser 3');
}

В этом примере создается желтый полупрозрачный div размером 300x200 пикселей с крупным жирным текстом 'Phaser 3' внутри. Координаты (400, 300) – это центр игрового поля размером 800x600. Важно: стили передаются обычной CSS-строкой, что открывает полную мощь CSS для оформления.

Позиционирование и привязка к игровому миру

DOM-элемент в Phaser ведет себя как обычный игровой объект: его позиция, масштаб, угол поворота и видимость управляются через свойства объекта. Чтобы визуализировать точку привязки (origin), в примере создается небольшой прямоугольник-маркер.

const marker = this.add.rectangle(400, 300, 16, 16, 0xff00ff);

Маркер размещен по тем же координатам (400, 300), что и DOM-элемент. Это показывает, что точка (0, 0) DOM-объекта (его верхний левый угол по умолчанию) будет совмещена с этой позицией на сцене. При анимации элемент будет вращаться и масштабироваться относительно этой точки.

Анимация DOM-объекта с помощью твинов

Phaser позволяет анимировать DOM-элементы через систему твинов точно так же, как спрайты или графику. В примере создается бесконечная пульсирующая анимация с поворотом.

this.tweens.add({
    targets: element,
    duration: 3000,
    angle: 360,
    scaleX: 2,
    scaleY: 2,
    ease: 'Sine.easeInOut',
    loop: -1,
    yoyo: true
});

* targets: element – указывает, что анимироваться будет наш DOM-объект. * angle: 360 – полный оборот на 360 градусов. * scaleX: 2, scaleY: 2 – увеличение масштаба в 2 раза. * ease: 'Sine.easeInOut' – плавное ускорение и замедление анимации. * loop: -1 – бесконечное повторение. * yoyo: true – после достижения конечных значений анимация проигрывается в обратном порядке, создавая эффект 'пульсации'.

Что попробовать дальше

Встраивание DOM-элементов в Phaser 3 – мощный инструмент для создания сложного интерфейса, форм ввода или отображения веб-контента прямо в игре. Вы можете экспериментировать: попробуйте создать выпадающий список (<select>), анимированную кнопку с CSS-переходами или встроить iframe с внешним контентом. Помните, что для интерактивных элементов (поля ввода, кнопки) может потребоваться дополнительная обработка событий фокуса.