Если вы когда-либо видели эффект фейерверка, созданный во Flash, я покажу вам, как воспроизвести эффект с использованием чистого JavaScript! Почему разработчики Flash имеют все удовольствие?
Настройка вашего рабочего пространства
Требования
Знание Javascript Object Notation. Если бы вы могли использовать какое-то обучение в этой области, нет проблем, Ли Кашик имеет подробное руководство по основам объектно-ориентированного JavaScript.
Базовые знания Raphael.js . Еще раз, если вы новичок в этом, то вы можете проверить Введение в библиотеку Raphael JS от Damian Dawber.
Что такое система частиц?
Система частиц, с точки зрения компьютерной графики, относится к воспроизведению поведения систем природных частиц в трехмерной модели, такой как взрывы, огонь, облака и множество других явлений, которые действительно трудно реализовать с помощью традиционных методов программирования.
Базовая система частиц состоит из —
- Эмиттер — точка в пространстве, где возникли частицы.
- Сцена — место, где находится система частиц.
- Силы — это внешние силы, которые влияют на движение частиц. В нашем уроке это будет гравитация.
Шаг 1
Мы начнем с создания нашего изображения частиц.
Откройте Photoshop и создайте холст размером 25 на 25 пикселей.
Создайте новый слой.
Выберите круглую кисть размером 23px с твердостью 100%. В этом уроке мы используем белый цвет, но вы можете выбрать любую форму кисти или цвет по своему усмотрению.
Теперь мы должны скрыть фоновый слой, а затем, используя опцию сохранения для веб-устройств и устройств, сохранить его как «icle_img »в формате png-24.
Шаг 2
Теперь давайте начнем с кодирования. Для начала вставьте следующий код.
01
02
03
04
05
06
07
08
09
10
|
<html>
<head>
<script type=»text/JavaScript» src=»raphael-min.js»></script>
<script type=»text/JavaScript» src=»sps.js»></script>
<title>Simple Particle System</title>
</head>
<body style=»background:#000000;color:#CCCCCC» onload=»startSystem()»>
<div id=»pane» ></div>
</body>
</html>
|
Это простой фрагмент HTML-кода, который состоит из:
- Импортируем raphael.js и sps.js, в которых мы будем работать с кодом JavaScript нашей системы частиц.
- Затем, в теле, есть div с идентификатором панели — это будет наша сцена.
- Тег body также состоит из функции startSystem (), которая будет вызываться при событии onload. Мы определим это позже в нашем файле JavaScript.
Шаг 3
Далее мы собираемся создать наш sps.js, в котором мы будем вводить фактический код для нашей системы частиц.
Шаг 4
Поскольку мы работаем с 2D-моделью, чтобы избежать использования в сценарии множества переменных x, y, мы создадим класс Vector, который позаботится о наших координатах.
Вектор функции () { this.x = 0; this.y = 0; //this.z = 0; }
Примечание. Мы не будем использовать координаты Z, поскольку нас не касается расстояния между частицами и глазами камеры (глаза), координата Z в основном относится к атрибутам масштаба и непрозрачности.
Шаг 5
Нам понадобятся функции для установки значений переменных и их добавления, поэтому мы объявим следующие функции в нашем классе Vector.
Вектор функции () { this.x = 0; this.y = 0; //this.z = 0; this.set = function (X, Y) // установка значений X, Y для нашего объекта { с этим) { х = х; y = Y; // z = Z; } } this.add = function (vector2) // добавление значений другого вектора в наш текущий векторный объект { this.x = this.x + vector2.x; this.y = this.y + vector2.y; //this.z = this.z + vector2.z; } }
Примечание. Обязательно добавьте Z в установленные параметры функции, если вы ее используете.
Шаг 6
Давайте создадим объект Vector, который будет содержать координаты происхождения частиц; также мы объявим глобальный объект Raphael и переменную таймера, которую мы будем использовать позже.
вар холст; // наш объект Рафаэля таймер вар; var emitter = new Vector (); emitter.set (400200);
Шаг 7
Нам нужно создать класс для наших объектов частиц, он будет состоять из основных свойств, таких как:
- Цвет и форма — основные свойства частицы.
- Размер — размер частицы.
- Местоположение — его точка происхождения.
- Скорость — скорость (здесь это будет относиться к распространению частиц на сцене).
- Ускорение — увеличение скорости.
- Продолжительность жизни — жизнь частицы.
В мире JavaScript мы немного изменим несколько переменных, таких как цвет и размер, которые уже были определены при создании изображения в Photoshop.
функция Particle () { this.size = Math.random () * 10 + 15; this.particle = canvas.image ("icle_img.png ", emitter.x, emitter.y, this.size, this.size); this.loc = new Vector (); this.vel = new Vector (); this.acc = new Vector (); this.lifespan = Math.random () * 250; }
В JavaScript классы объявляются с помощью функции, а ее переменные объявляются с помощью этого .
- Мы хотим, чтобы размер частиц генерировался случайным образом — от 15 до 25.
- Частица — это объект изображения Рафаэля с именем, координатами и размером изображения в качестве параметров.
- loc это местоположение частицы.
- акк ускорение.
- vel — это скорость.
- продолжительность жизни — это период, в котором частица живет на сцене.
Шаг 8
Нам нужно будет создать функции для следующих условий:
- Создание частицы на холсте с заявленными выше свойствами.
- Постоянно обновляет свою позицию относительно своего ускорения.
- Проверяя, мертва ли частица, мы должны удалить ее с холста, иначе наша сцена будет полна мертвых частиц :).
Шаг 9
Сначала мы объявим функцию init, которую будем использовать для инициализации наших частиц.
this.init = function () { с этим) { particle.rotate (Math.random () * 360); acc.set (0,0.05); vel.set (Math.random () * 4 -2, Math.random () * 3 -1); loc.set (emitter.x, emitter.y); } }
Здесь мы обернули код внутри with (this), который ссылается на текущий объект частицы.
- Параметрicle.rotate () используется для случайного поворота объекта от 0 до 360 градусов. В этом случае это не имеет значения, поскольку мы используем круглый объект, однако, с другими объектами, такими как звезды, это имеет значение, поскольку выглядит странным, что все частицы имеют одинаковые геометрические углы.
- Мы установим начальное ускорение на 0,0,5, потому что мы хотим показать, как частицы связаны с гравитацией; Вот почему мы инициализировали координату у. По мере увеличения значения ускорения скорость частиц увеличивается.
- Здесь vel относится к распространению частиц на сцене — то есть Math.random () * 4 -2 будет генерировать числа в диапазоне от -2 до 2.
- loc принимает начальные значения частицы.
Следует отметить несколько моментов:
- Условие для ускорения
- Положительные значения увеличивают ускорение.
- Для гравитационной стадии ускорение = 0.
- Для обратной гравитации следует использовать отрицательные значения.
- Условия для вел
- Для увеличения спреда мы будем использовать большее значение диапазона, сгенерированного из Math.random ().
- Для испускающих частицы в определенной стороне мы можем достигнуть этого, умножая на максимальное положительное или отрицательное число.
Шаг 10
Теперь мы создадим функцию для обновления значений частицы до ее новой позиции.
this.update = function () { с этим) { vel.add (соотв); loc.add (VEL); продолжительность жизни - = 1; particle.animate ({х: loc.x, у: loc.y}, 39); } }
Здесь всякий раз, когда вызывается функция обновления, ускорение добавляется к vel, а это добавляется к местоположению. Наконец, частица обновляется до своего нового местоположения. Когда будет добавлено постоянное ускорение, мы создадим впечатление, что частица находится под действием некоторой силы, поскольку она должна охватывать более отдаленные в единицу времени Кроме того, всякий раз, когда вызывается обновление, его срок службы уменьшается на 1.
Шаг 11
Наконец, для класса частиц мы собираемся создать функцию, чтобы проверить, закончился ли срок жизни частицы или нет.
this.dead = function () { если (this.lifespan <0) { вернуть истину; } еще { вернуть ложь; } }
Шаг 12
Наш класс частиц выглядит так:
функция Particle () { this.size = Math.random () * 10 + 15; this.particle = r.image ("icle_img.png ", emitter.x, emitter.y, this.size, this.size); this.loc = new Vector (); this.vel = new Vector (); this.acc = new Vector (); this.lifespan = Math.random () * 250; this.init = function () { с этим) { particle.rotate (Math.random () * 360); acc.set (0,0.05); vel.set (Math.random () * 4 -2, Math.random () * 3 -1); loc.set (emitter.x, emitter.y); } } this.update = function () { с этим) { vel.add (соотв); loc.add (VEL); продолжительность жизни - = 1; particle.animate ({х: loc.x, у: loc.y}, 39); } } this.dead = function () { если (this.lifespan <0) { вернуть истину; } еще { вернуть ложь; } } }
Шаг 13
Теперь мы создадим класс системы частиц. Давайте начнем с объявления переменной-члена.
this.particles = new Array ();
Здесь частицы — это массив объектов Particles, которые мы скоро создадим.
Шаг 14
Теперь нам нужно создать функции для инициализации и запуска нашей системы частиц; поэтому мы начнем с создания нашей функции init.
this.init = function (num) { для (var i = 0; i <num; i ++) { this.particles [i] = new Particle (); this.particles [I] .init (); } }
Во-первых, мы берем количество частиц, которые будут созданы в качестве параметров функции. Затем, используя цикл for, мы создаем объекты частиц и инициализируем их, вызывая их функцию init.
Шаг 15
Теперь мы создадим функцию запуска, которая будет запускать нашу систему частиц.
this.run = function () { с этим){ timer = setInterval (function () { для (я = частица длина -1; я> = 0; я--) { if (частицы [i] .dead ()) { частицы [частица-длина -1] .particle.remove (); particles.pop (); var temp = new Particle (); temp.init (); particles.unshift (температура); } частицы [I] .update (); } }, 40); } }
Здесь наш код находится внутри блока with (this), который ссылается на текущий объект системы частиц. Теперь, поскольку наши частицы должны постоянно обновляться до следующего местоположения, мы вызываем функцию update () частицы внутри функции setInterval (), которая выполняет функцию в определенный интервал времени. Мы обновляем все позиционирование частиц, перебирая массив частиц.
Теперь мы также хотим проверить, мертва ли частица или нет. Мы выполняем эту задачу, вызывая функцию dead () частицы. Если частица мертва, мы делаем следующее:
- Удалите его из нашего массива.
- сдвигать элементы назад на один, начиная с позиции после индекса мертвой частицы.
- Вставьте новую частицу в конец массива.
var p = частицы [i]; для (var j = i; j <частиц. длина-1; j ++) { частицы [j] = частицы [j + 1]; } p.particle.remove (); var temp = new Particle (); temp.init (); particles.push (температура);
Приведенный выше код является оптимальным решением, но когда мы реализуем его в мире JavasSript, передача происходит настолько спонтанно, что движки зависают. Вот почему мы использовали альтернативный код для увеличения сложности и визуализации более плавной анимации. Вы можете попробовать это сами;).
Поскольку период времени составляет порядка миллисекунд, поэтому, несмотря на использование более сложного алгоритма, мы получаем спонтанное излучение.
Шаг 16
На данный момент наш класс ParticleSystem выглядит так.
функция ParticleSystem () { this.particles = new Array (); this.init = function (num) { для (var i = 0; i <num; i ++) { this.particles [i] = new Particle (); this.particles [I] .init (); } } this.run = function () { с этим){ timer = setInterval (function () { для (я = частица длина -1; я> = 0; я--) { if (частицы [i] .dead ()) { частицы [частица-длина -1] .particle.remove (); particles.pop (); var temp = new Particle (); temp.init (); particles.unshift (температура); } частицы [I] .update (); } }, 40); } } }
Шаг 17
Теперь мы объявим нашу функцию startSystem (), которая будет инициировать систему частиц.
startSystem = function () { W = 800; H = 400; холст = Рафаэль ("панель", W, H); var ps = new ParticleSystem (); var iniVec = new Vector (); iniVec.set (emitter.x, emitter.y); ps.init (20, iniVec); ps.run (); }
Мы инициализируем наш объект Raphael с идентификатором сцены, шириной и высотой. Затем мы создаем наш объект системы частиц и создаем векторный объект с исходными координатами. Затем мы инициализируем нашу систему частиц, вызывая init, который, в свою очередь, инициализирует частицы. Мы также предоставляем 20 как количество частиц в параметрах.
Количество частиц должно быть от 20 до 30 для плавного эффекта анимации. Если указать большее число, браузер будет зависать или зависать!
Шаг 18
Вот как выглядит код нашего файла sps.js на данный момент.
Вектор функции () { this.x = 0; this.y = 0; //this.z = 0; this.set = функция (X, Y) { с этим) { х = х; y = Y; // z = Z; } } this.add = function (vector2) { this.x = this.x + vector2.x; this.y = this.y + vector2.y; //this.z = this.z + vector2.z; } } вар холст; // наш объект Рафаэля таймер вар; var emitter = new Vector (); emitter.set (400200); функция Particle () { this.size = Math.random () * 10 + 15; this.particle = canvas.image ("img1.png", emitter.x, emitter.y, this.size, this.size); this.loc = new Vector (); this.vel = new Vector (); this.acc = new Vector (); this.lifespan = Math.random () * 250; this.init = function () { с этим) { particle.rotate (Math.random () * 360); acc.set (0,0.05); vel.set (Math.random () * 4 -2, Math.random () * 3 -1); loc.set (emitter.x, emitter.y); } } this.update = function () { с этим) { vel.add (соотв); loc.add (VEL); продолжительность жизни - = 1; particle.animate ({х: loc.x, у: loc.y}, 39); } } this.dead = function () { если (this.lifespan <0) { вернуть истину; } еще { вернуть ложь; } } } функция ParticleSystem () { this.particles = new Array (); this.init = function (num) { для (var i = 0; i <num; i ++) { this.particles [i] = new Particle (); this.particles [I] .init (); } } this.run = function () { с этим){ timer = setInterval (function () { для (я = частица длина -1; я> = 0; я--) { if (частицы [i] .dead ()) { частицы [частица-длина -1] .particle.remove (); particles.pop (); var temp = new Particle (); temp.init (); particles.unshift (температура); } частицы [I] .update (); } }, 40); } } } startSystem = function () { W = 800; H = 400; холст = Рафаэль ("панель", W, H); var ps = new ParticleSystem (); ps.init (20); ps.run (); }
Наконец, мы закончили. Этот небольшой проект совместим со всеми браузерами, даже в Internet Explorer, хотя в IE6 есть некоторые проблемы с прозрачностью. Эту систему частиц можно использовать практически где угодно, включая фоны, эффекты взрыва, логотипы и заставки заголовков и т. Д. Я создал три демонстрации, которые являются модифицированными версиями кода выше. Одна из них реализует различные системы частиц, такие как дым, пыль и система частиц боке. Наслаждайтесь и спасибо за чтение!