Плотность и распределение частиц

В системе анимации частиц в mo.js плотность определяется не только количеством объектов, но и тем, как они распределяются в пространстве, времени и направлении. Основные параметры, влияющие на плотность, находятся в конфигурации Burst, Shape и пользовательских композициях через timeline.

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

const burst = new mojs.Burst({
  radius: { 0: 100 },
  count: 20,
  children: {
    shape: 'circle',
    radius: 5,
    fill: 'cyan'
  }
});

При увеличении count плотность возрастает линейно, но визуальное восприятие зависит также от радиуса распределения и углового разброса.


Радиальное распределение и влияние радиуса

В mo.js частицы часто распределяются по окружности или внутри расширяющегося радиуса. Параметр radius может задавать диапазон:

radius: { 0: 120 }

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

Плотность в радиальном распределении можно условно рассматривать как отношение количества частиц к площади круга:

  • малая площадь → высокая концентрация
  • большая площадь → рассеянная структура

Для более управляемого эффекта используется комбинация radius и angleSpread.


Угловое распределение и направленность

Параметр angleSpread контролирует сектор, в котором появляются частицы:

children: {
  angle: { 0: 360 },
  angleSpread: 180
}

При angleSpread: 360 частицы распределяются равномерно по окружности. При уменьшении значения формируется направленный поток.

Фактически, плотность в угловом измерении становится функцией:

  • количества частиц
  • углового диапазона

Чем меньше угол при том же count, тем выше локальная плотность потока.


Стохастическое распределение и шум

mo.js поддерживает вариативность через диапазоны значений. Это ключевой механизм создания «естественной» плотности.

Пример случайного радиуса:

children: {
  radius: { 3: 8 },
  duration: { 500: 1200 },
  delay: 'stagger(50)'
}

Диапазоны создают неравномерность, которая визуально воспринимается как более высокая сложность распределения.

Использование stagger добавляет временную плотность: частицы не появляются одновременно, а формируют поток.


Контроль плотности через временные параметры

Плотность — это не только пространственная характеристика, но и временная.

Параметры:

  • duration — длительность жизни частицы
  • delay — задержка появления
  • stagger() — последовательный запуск

Пример временного сгущения:

const burst = new mojs.Burst({
  radius: { 0: 150 },
  count: 30,
  timeline: { delay: 0 },
  children: {
    shape: 'circle',
    radius: 4,
    duration: 800,
    delay: 'stagger(10)',
    fill: 'orange'
  }
});

При уменьшении duration частицы быстрее исчезают, освобождая пространство и снижая накопленную плотность. При увеличении задержек возникает эффект волнового распределения.


Многоуровневая плотность через вложенные burst

Одним из наиболее мощных способов управления распределением является вложение нескольких Burst с разными параметрами.

const burst = new mojs.Burst({
  radius: { 0: 120 },
  count: 10,
  children: {
    shape: 'circle',
    radius: 6,
    fill: 'yellow'
  }
});

const innerBurst = new mojs.Burst({
  radius: { 0: 60 },
  count: 30,
  children: {
    shape: 'circle',
    radius: 3,
    fill: 'white'
  }
});

Комбинация создаёт неоднородное распределение:

  • внутренний слой — высокая плотность
  • внешний слой — низкая плотность

Так формируется визуальная глубина без усложнения геометрии.


Линейное распределение частиц

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

const lineBurst = new mojs.Burst({
  radius: { 0: 200 },
  angle: 0,
  count: 15,
  children: {
    shape: 'line',
    stroke: 'white',
    strokeWidth: 3,
    radius: { 10: 50 },
    angle: { 0: 0 }
  }
});

В линейных распределениях плотность зависит от:

  • количества элементов на оси
  • длины траектории
  • скорости движения

Чем меньше расстояние между элементами при фиксированной длине, тем выше визуальная плотность потока.


Градиент плотности и масштабирование

Плотность может изменяться по радиусу или времени через функции масштабирования.

children: {
  radius: (progress) => 5 + 10 * progress,
  opacity: { 1: 0 }
}

Функции позволяют задавать нелинейные распределения. Это создаёт эффект:

  • уплотнения в начале траектории
  • разрежения к концу
  • или наоборот

Такая техника особенно полезна для имитации взрывов, дыма или энергии.


Случайное распределение с ограничениями

Полная случайность редко используется без ограничений, так как она разрушает читаемость композиции. Поэтому применяется ограниченный рандом:

children: {
  x: { -50: 50 },
  y: { -50: 50 },
  radius: { 2: 6 }
}

Это создаёт равномерное распределение внутри заданного квадрата.

Для кругового распределения используется комбинация угла и радиуса:

children: {
  angle: { 0: 360 },
  radius: { 20: 100 }
}

Так формируется плотность внутри кольца, а не по окружности.


Плотность как функция количества систем

В сложных сценах плотность определяется не одним burst, а суммой всех активных систем.

Если одновременно работают:

  • несколько Burst
  • Shape-анимации
  • Tween-переходы

то возникает перекрытие частиц, что увеличивает визуальную насыщенность.

Контроль достигается через:

  • синхронизацию timeline
  • ограничение count
  • разделение радиусов

Оптимизация плотных сцен

Высокая плотность напрямую влияет на производительность, так как mo.js оперирует DOM-элементами или canvas-слоями в зависимости от конфигурации.

Основные ограничения:

  • большое count увеличивает количество узлов
  • длительный duration приводит к накоплению частиц
  • высокая частота burst создаёт нагрузку на рендер

Практика управления плотностью включает:

children: {
  isShowStart: false,
  easing: 'sin.out',
  duration: 600
}

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

if (!isAnimating) {
  burst.replay();
}

Адаптивная плотность

Плотность может изменяться в зависимости от внешних параметров: скорости курсора, частоты кликов, или состояния интерфейса.

Пример адаптивного подхода:

document.addEventListener('mousemove', (e) => {
  new mojs.Burst({
    left: e.pageX,
    top: e.pageY,
    count: Math.min(10, Math.floor(e.movementX)),
    radius: { 0: 50 },
    children: {
      shape: 'circle',
      fill: 'blue'
    }
  }).play();
});

Здесь плотность напрямую зависит от интенсивности движения.


Геометрические модели распределения

В продвинутых сценах используются математические модели:

  • равномерное распределение по окружности (angle step)
  • полярные координаты (radius + angle)
  • гауссово распределение (через пользовательские функции)

Пример равномерного шага:

const count = 12;
const step = 360 / count;

children: Array.from({ length: count }).map((_, i) => ({
  angle: i * step
}));

Такая модель создаёт строгую симметрию и контролируемую плотность без случайности.


Визуальная интерпретация плотности

Плотность в mo.js воспринимается не математически, а визуально через:

  • перекрытие частиц
  • частоту появления
  • расстояние между элементами
  • контраст с фоном

Одинаковое количество частиц может выглядеть по-разному в зависимости от:

  • размера radius
  • прозрачности opacity
  • скорости duration

Поэтому плотность является многомерным параметром, зависящим от всей конфигурации анимации, а не от одного значения count.