tsparticles
Version:
Easily create highly customizable particle animations and use them as animated backgrounds for your website. Ready to use components available also for React, Vue.js (2.x and 3.x), Angular, Svelte, jQuery, Preact, Riot.js, Inferno.
220 lines (219 loc) • 8.92 kB
JavaScript
import { ColorUtils, NumberUtils, Utils } from "../../Utils";
import { SizeMode } from "../../Enums";
import { EmitterSize } from "./Options/Classes/EmitterSize";
function randomCoordinate(position, offset) {
return position + offset * (Math.random() - 0.5);
}
function randomPosition(position, offset) {
return {
x: randomCoordinate(position.x, offset.x),
y: randomCoordinate(position.y, offset.y),
};
}
export class EmitterInstance {
constructor(emitters, container, emitterOptions, position) {
var _a, _b, _c, _d;
this.emitters = emitters;
this.container = container;
this.firstSpawn = true;
this.currentDuration = 0;
this.currentEmitDelay = 0;
this.currentSpawnDelay = 0;
this.initialPosition = position;
this.emitterOptions = Utils.deepExtend({}, emitterOptions);
this.spawnDelay = (((_a = this.emitterOptions.life.delay) !== null && _a !== void 0 ? _a : 0) * 1000) / this.container.retina.reduceFactor;
this.position = (_b = this.initialPosition) !== null && _b !== void 0 ? _b : this.calcPosition();
this.name = emitterOptions.name;
let particlesOptions = Utils.deepExtend({}, this.emitterOptions.particles);
if (particlesOptions === undefined) {
particlesOptions = {};
}
if (particlesOptions.move === undefined) {
particlesOptions.move = {};
}
if (particlesOptions.move.direction === undefined) {
particlesOptions.move.direction = this.emitterOptions.direction;
}
if (this.emitterOptions.spawnColor !== undefined) {
this.spawnColor = ColorUtils.colorToHsl(this.emitterOptions.spawnColor);
}
this.paused = !this.emitterOptions.autoPlay;
this.particlesOptions = particlesOptions;
this.size =
(_c = this.emitterOptions.size) !== null && _c !== void 0 ? _c : (() => {
const size = new EmitterSize();
size.load({
height: 0,
mode: SizeMode.percent,
width: 0,
});
return size;
})();
this.lifeCount = (_d = this.emitterOptions.life.count) !== null && _d !== void 0 ? _d : -1;
this.immortal = this.lifeCount <= 0;
this.play();
}
externalPlay() {
this.paused = false;
this.play();
}
externalPause() {
this.paused = true;
this.pause();
}
play() {
if (this.paused) {
return;
}
if (this.container.retina.reduceFactor &&
(this.lifeCount > 0 || this.immortal || !this.emitterOptions.life.count)) {
if (this.emitDelay === undefined) {
this.emitDelay = (1000 * this.emitterOptions.rate.delay) / this.container.retina.reduceFactor;
}
if (this.lifeCount > 0 || this.immortal) {
this.prepareToDie();
}
}
}
pause() {
if (this.paused) {
return;
}
delete this.emitDelay;
}
resize() {
const initialPosition = this.initialPosition;
this.position =
initialPosition && Utils.isPointInside(initialPosition, this.container.canvas.size)
? initialPosition
: this.calcPosition();
}
update(delta) {
var _a, _b, _c;
if (this.paused) {
return;
}
if (this.firstSpawn) {
this.firstSpawn = false;
this.currentSpawnDelay = (_a = this.spawnDelay) !== null && _a !== void 0 ? _a : 0;
this.currentEmitDelay = (_b = this.emitDelay) !== null && _b !== void 0 ? _b : 0;
delta.value = 0;
}
if (this.duration !== undefined) {
this.currentDuration += delta.value;
if (this.currentDuration >= this.duration) {
this.pause();
if (this.spawnDelay !== undefined) {
delete this.spawnDelay;
}
if (!this.immortal) {
this.lifeCount--;
}
if (this.lifeCount > 0 || this.immortal) {
this.position = this.calcPosition();
this.spawnDelay =
(((_c = this.emitterOptions.life.delay) !== null && _c !== void 0 ? _c : 0) * 1000) / this.container.retina.reduceFactor;
}
else {
this.destroy();
}
this.currentDuration -= this.duration;
delete this.duration;
}
}
if (this.spawnDelay !== undefined) {
this.currentSpawnDelay += delta.value;
if (this.currentSpawnDelay >= this.spawnDelay) {
this.play();
this.currentSpawnDelay -= this.currentSpawnDelay;
delete this.spawnDelay;
}
}
if (this.emitDelay !== undefined) {
this.currentEmitDelay += delta.value;
if (this.currentEmitDelay >= this.emitDelay) {
this.emit();
this.currentEmitDelay -= this.emitDelay;
}
}
}
prepareToDie() {
var _a;
if (this.paused) {
return;
}
const duration = (_a = this.emitterOptions.life) === null || _a === void 0 ? void 0 : _a.duration;
if (this.container.retina.reduceFactor &&
(this.lifeCount > 0 || this.immortal) &&
duration !== undefined &&
duration > 0) {
this.duration = duration * 1000;
}
}
destroy() {
this.emitters.removeEmitter(this);
}
calcPosition() {
var _a, _b;
const container = this.container;
const percentPosition = this.emitterOptions.position;
return {
x: (((_a = percentPosition === null || percentPosition === void 0 ? void 0 : percentPosition.x) !== null && _a !== void 0 ? _a : Math.random() * 100) / 100) * container.canvas.size.width,
y: (((_b = percentPosition === null || percentPosition === void 0 ? void 0 : percentPosition.y) !== null && _b !== void 0 ? _b : Math.random() * 100) / 100) * container.canvas.size.height,
};
}
emit() {
var _a;
if (this.paused) {
return;
}
const container = this.container;
const position = this.position;
const offset = {
x: this.size.mode === SizeMode.percent
? (container.canvas.size.width * this.size.width) / 100
: this.size.width,
y: this.size.mode === SizeMode.percent
? (container.canvas.size.height * this.size.height) / 100
: this.size.height,
};
for (let i = 0; i < this.emitterOptions.rate.quantity; i++) {
const particlesOptions = Utils.deepExtend({}, this.particlesOptions);
if (this.spawnColor !== undefined) {
const colorAnimation = (_a = this.emitterOptions.spawnColor) === null || _a === void 0 ? void 0 : _a.animation;
if (colorAnimation) {
const hueAnimation = colorAnimation;
if (hueAnimation.enable) {
this.spawnColor.h = this.setColorAnimation(hueAnimation, this.spawnColor.h, 360);
}
else {
const hslAnimation = colorAnimation;
this.spawnColor.h = this.setColorAnimation(hslAnimation.h, this.spawnColor.h, 360);
this.spawnColor.s = this.setColorAnimation(hslAnimation.s, this.spawnColor.s, 100);
this.spawnColor.l = this.setColorAnimation(hslAnimation.l, this.spawnColor.l, 100);
}
}
if (!particlesOptions.color) {
particlesOptions.color = {
value: this.spawnColor,
};
}
else {
particlesOptions.color.value = this.spawnColor;
}
}
container.particles.addParticle(randomPosition(position, offset), particlesOptions);
}
}
setColorAnimation(animation, initValue, maxValue) {
var _a;
const container = this.container;
if (!animation.enable) {
return initValue;
}
const colorOffset = NumberUtils.randomInRange(animation.offset);
const emitFactor = (1000 * this.emitterOptions.rate.delay) / container.retina.reduceFactor;
const colorSpeed = (_a = animation.speed) !== null && _a !== void 0 ? _a : 0;
return (initValue + (colorSpeed * container.fpsLimit) / emitFactor + colorOffset * 3.6) % maxValue;
}
}