Сортировка дочерних элементов

В PixiJS каждая сцена или контейнер представляет собой объект PIXI.Container, который может содержать любое количество дочерних элементов. Порядок этих элементов внутри контейнера напрямую влияет на отрисовку: элементы, добавленные позже, перекрывают элементы, добавленные раньше. Для управления визуальным порядком используется сортировка дочерних объектов.


Свойство children и его значение

У контейнера есть массив children, содержащий все дочерние элементы в порядке их добавления. Этот массив является основной структурой, определяющей порядок рендеринга.

Пример:

const container = new PIXI.Container();

const sprite1 = PIXI.Sprite.from('image1.png');
const sprite2 = PIXI.Sprite.from('image2.png');

container.addChild(sprite1);
container.addChild(sprite2);

console.log(container.children); // [sprite1, sprite2]

В этом случае sprite2 будет нарисован поверх sprite1.


Метод sortChildren()

Для упорядочивания дочерних элементов контейнера можно использовать метод sortChildren(). Этот метод принимает функцию сравнения, аналогичную той, что используется в Array.prototype.sort().

Пример сортировки по координате y:

container.sortChildren((a, b) => a.y - b.y);

После выполнения этого кода элементы с меньшей координатой y будут рисоваться снизу, а с большей — сверху, что позволяет реализовать эффект глубины в 2D-сцене.


Влияние свойства zIndex

С версии PixiJS 5 появился механизм zIndex, который позволяет задавать визуальный порядок без изменения порядка элементов в массиве children.

Пример:

sprite1.zIndex = 10;
sprite2.zIndex = 5;

container.sortChildren(); // сортировка по zIndex

Здесь элемент с большим zIndex будет нарисован поверх элементов с меньшим zIndex. Важно помнить, что без вызова sortChildren() значения zIndex не будут применены автоматически.

Особенности работы zIndex:

  • Работает только на дочерних элементах одного контейнера.
  • По умолчанию zIndex = 0.
  • Сортировка по zIndex не затрагивает физический порядок в массиве children, если не вызвать sortChildren().

Сортировка при динамических изменениях

При анимации или интерактивных сцен часто требуется менять порядок объектов на лету. В таких случаях рекомендуется:

  1. Изменять значение zIndex или ключевое свойство, по которому будет сортировка.
  2. Вызывать container.sortChildren() после изменения.

Пример динамической сортировки:

app.ticker.add(() => {
    container.children.forEach(sprite => {
        sprite.y += Math.random() * 2 - 1; // движение по y
    });
    container.sortChildren((a, b) => a.y - b.y); // обновление порядка рендеринга
});

Этот подход позволяет создавать эффект глубины, когда объекты перемещаются “вперед” или “назад” на сцене.


Альтернативные подходы: addChildAt() и removeChild()

Если нужно вставить объект на конкретную позицию в массиве children, можно использовать метод addChildAt().

container.addChildAt(sprite, 0); // вставка sprite в начало контейнера

Для изменения позиции уже существующего объекта можно комбинировать removeChild() и addChildAt().

container.removeChild(sprite);
container.addChildAt(sprite, container.children.length); // перемещаем в конец

Этот метод полезен для фиксированной перестановки элементов, когда порядок не определяется динамическими свойствами.


Производительность сортировки

Сортировка большого количества элементов может быть затратной по ресурсам. Практика показывает:

  • Минимизировать вызовы sortChildren() в каждом кадре.
  • Сортировать только при изменении ключевых параметров (y, zIndex, другие пользовательские свойства).
  • Для сложных сцен использовать отдельные контейнеры с собственной сортировкой, чтобы уменьшить количество элементов в одном массиве children.

Пользовательские функции сортировки

Метод sortChildren() поддерживает любые функции сравнения. Например, комбинированная сортировка по координате y и масштабу:

container.sortChildren((a, b) => {
    if (a.y === b.y) {
        return b.scale.x - a.scale.x; // при равных y сравниваем по масштабу
    }
    return a.y - b.y;
});

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


Итоговое понимание

Управление порядком дочерних элементов в PixiJS — это сочетание физического порядка в массиве children и логики zIndex, дополняемое динамическими сортировками. Использование этих инструментов дает полный контроль над тем, какие объекты и в каком порядке будут визуально отображены на сцене, что особенно важно для 2D-игр и интерактивной графики.