Эмиттеры

Эмиттеры в Paper.js используются для создания динамических визуальных эффектов, таких как частицы, дым, огонь или снег. Они позволяют генерировать объекты с определёнными свойствами и управлять их поведением во времени, используя комбинацию геометрии, анимации и событий. В Paper.js эмиттер реализуется через классы Item, Path, Shape, и собственные функции обновления состояния частиц.

Создание эмиттера

Для начала нужно определить область, из которой будут рождаться частицы, и задать базовые параметры: скорость, направление, размер, цвет и продолжительность жизни. Обычно для эмиттера создаётся отдельный объект, который хранит массив частиц и методы их обновления.

class Particle {
    constructor(position, velocity, life, color, radius) {
        this.position = position.clone();
        this.velocity = velocity.clone();
        this.life = life;
        this.color = color;
        this.radius = radius;
        this.shape = new Path.Circle({
            center: this.position,
            radius: this.radius,
            fillColor: this.color
        });
    }

    update() {
        this.position = this.position.add(this.velocity);
        this.life -= 1;
        this.shape.position = this.position;
        if (this.life <= 0) {
            this.shape.remove();
        }
    }
}

class Emitter {
    constructor(position, options) {
        this.position = position.clone();
        this.options = options;
        this.particles = [];
    }

    emit() {
        for (let i = 0; i < this.options.count; i++) {
            const velocity = new Point(
                (Math.random() - 0.5) * this.options.speed,
                (Math.random() - 0.5) * this.options.speed
            );
            const particle = new Particle(
                this.position,
                velocity,
                this.options.life,
                this.options.color,
                this.options.radius
            );
            this.particles.push(particle);
        }
    }

    update() {
        this.particles = this.particles.filter(p => p.life > 0);
        this.particles.forEach(p => p.update());
    }
}

Управление поведением частиц

Скорость и направление. Скорость задаётся через вектор velocity. Для создания эффекта ветра или гравитации вектор можно изменять на каждом кадре.

particle.velocity = particle.velocity.add(new Point(0, 0.1)); // имитация гравитации

Продолжительность жизни. Каждая частица имеет параметр life, который уменьшается с каждым кадром. При достижении нуля частица удаляется из сцены, что предотвращает переполнение памяти.

Изменение цвета и прозрачности. Для плавных переходов цвета и альфа-канала можно использовать интерполяцию:

particle.shape.fillColor.alpha = particle.life / maxLife;

Интеграция с Paper.js

Эмиттеры идеально интегрируются с функцией view.onFrame, которая выполняется каждый кадр анимации:

const emitter = new Emitter(new Point(300, 200), {
    count: 5,
    speed: 3,
    life: 100,
    color: 'orange',
    radius: 5
});

view.onFr ame = function(event) {
    emitter.emit();
    emitter.update();
};

В этом примере каждая итерация onFrame создаёт новые частицы и обновляет существующие, обеспечивая непрерывный поток.

Разнообразие форм частиц

Для большей выразительности частицы могут быть не только круглыми, но и в виде линий, многоугольников или кривых Безье. Paper.js позволяет создавать Path объектов любой формы и изменять их динамически:

class TriangleParticle extends Particle {
    constructor(position, velocity, life, color, size) {
        super(position, velocity, life, color, size);
        this.shape.remove(); // удаляем круг
        this.shape = new Path.RegularPolygon({
            center: this.position,
            sides: 3,
            radius: size,
            fillColor: color
        });
    }
}

Оптимизация производительности

При большом количестве частиц важно следить за оптимизацией:

  • Удалять частицы сразу после окончания жизни (shape.remove()).
  • Использовать простые формы вместо сложных кривых.
  • Ограничивать максимальное количество частиц на экране.
  • Объединять обновления нескольких частиц в один цикл, чтобы минимизировать количество рендеров.

Взаимодействие с событиями

Эмиттеры могут реагировать на пользовательские события, например на движения мыши:

tool.onMouseM ove = function(event) {
    emitter.position = event.point;
};

Это позволяет создавать эффекты, которые следуют за курсором или реагируют на клики.

Сложные эффекты и слои

Для сложных визуальных эффектов эмиттеры можно комбинировать:

  • Несколько эмиттеров на разных слоях (Layer) для наложения эффектов.
  • Использование градиентов и масок для создания дымки и огня.
  • Изменение скорости, направления и прозрачности частиц с течением времени для имитации физики среды.

Эмиттеры в Paper.js становятся мощным инструментом визуализации, когда комбинируются с векторной графикой, анимацией и интерактивными событиями. Их гибкость позволяет создавать как простые частицы, так и сложные динамические сцены с естественным движением объектов.