258 lines
10 KiB
JavaScript
258 lines
10 KiB
JavaScript
import { Vector, calcPositionOrRandomFromSizeRanged, deepExtend, getRangeValue, isPointInside, itemFromSingleOrMultiple, randomInRange, rangeColorToHsl, } from "tsparticles-engine";
|
|
import { Emitter } from "./Options/Classes/Emitter";
|
|
import { EmitterSize } from "./Options/Classes/EmitterSize";
|
|
export class EmitterInstance {
|
|
constructor(engine, emitters, container, options, position) {
|
|
var _a, _b, _c, _d, _e, _f, _g;
|
|
var _h;
|
|
this.emitters = emitters;
|
|
this.container = container;
|
|
this._engine = engine;
|
|
this._currentDuration = 0;
|
|
this._currentEmitDelay = 0;
|
|
this._currentSpawnDelay = 0;
|
|
this._initialPosition = position;
|
|
if (options instanceof Emitter) {
|
|
this.options = options;
|
|
}
|
|
else {
|
|
this.options = new Emitter();
|
|
this.options.load(options);
|
|
}
|
|
this._spawnDelay = (((_a = this.options.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 = this.options.name;
|
|
this._shape = (_c = this._engine.emitterShapeManager) === null || _c === void 0 ? void 0 : _c.getShape(this.options.shape);
|
|
this.fill = this.options.fill;
|
|
this._firstSpawn = !this.options.life.wait;
|
|
this._startParticlesAdded = false;
|
|
let particlesOptions = deepExtend({}, this.options.particles);
|
|
particlesOptions !== null && particlesOptions !== void 0 ? particlesOptions : (particlesOptions = {});
|
|
(_d = particlesOptions.move) !== null && _d !== void 0 ? _d : (particlesOptions.move = {});
|
|
(_e = (_h = particlesOptions.move).direction) !== null && _e !== void 0 ? _e : (_h.direction = this.options.direction);
|
|
if (this.options.spawnColor) {
|
|
this.spawnColor = rangeColorToHsl(this.options.spawnColor);
|
|
}
|
|
this._paused = !this.options.autoPlay;
|
|
this._particlesOptions = particlesOptions;
|
|
this.size =
|
|
(_f = this.options.size) !== null && _f !== void 0 ? _f : (() => {
|
|
const size = new EmitterSize();
|
|
size.load({
|
|
height: 0,
|
|
mode: "percent",
|
|
width: 0,
|
|
});
|
|
return size;
|
|
})();
|
|
this._lifeCount = (_g = this.options.life.count) !== null && _g !== void 0 ? _g : -1;
|
|
this._immortal = this._lifeCount <= 0;
|
|
this._engine.dispatchEvent("emitterCreated", {
|
|
container,
|
|
data: {
|
|
emitter: this,
|
|
},
|
|
});
|
|
this.play();
|
|
}
|
|
externalPause() {
|
|
this._paused = true;
|
|
this.pause();
|
|
}
|
|
externalPlay() {
|
|
this._paused = false;
|
|
this.play();
|
|
}
|
|
getPosition() {
|
|
if (this.options.domId) {
|
|
const container = this.container, element = document.getElementById(this.options.domId);
|
|
if (element) {
|
|
const elRect = element.getBoundingClientRect();
|
|
return {
|
|
x: (elRect.x + elRect.width / 2) * container.retina.pixelRatio,
|
|
y: (elRect.y + elRect.height / 2) * container.retina.pixelRatio,
|
|
};
|
|
}
|
|
}
|
|
return this.position;
|
|
}
|
|
getSize() {
|
|
const container = this.container;
|
|
if (this.options.domId) {
|
|
const element = document.getElementById(this.options.domId);
|
|
if (element) {
|
|
const elRect = element.getBoundingClientRect();
|
|
return {
|
|
width: elRect.width * container.retina.pixelRatio,
|
|
height: elRect.height * container.retina.pixelRatio,
|
|
};
|
|
}
|
|
}
|
|
return {
|
|
width: this.size.mode === "percent"
|
|
? (container.canvas.size.width * this.size.width) / 100
|
|
: this.size.width,
|
|
height: this.size.mode === "percent"
|
|
? (container.canvas.size.height * this.size.height) / 100
|
|
: this.size.height,
|
|
};
|
|
}
|
|
pause() {
|
|
if (this._paused) {
|
|
return;
|
|
}
|
|
delete this._emitDelay;
|
|
}
|
|
play() {
|
|
var _a;
|
|
if (this._paused) {
|
|
return;
|
|
}
|
|
if (!(this.container.retina.reduceFactor &&
|
|
(this._lifeCount > 0 || this._immortal || !this.options.life.count) &&
|
|
(this._firstSpawn || this._currentSpawnDelay >= ((_a = this._spawnDelay) !== null && _a !== void 0 ? _a : 0)))) {
|
|
return;
|
|
}
|
|
if (this._emitDelay === undefined) {
|
|
const delay = getRangeValue(this.options.rate.delay);
|
|
this._emitDelay = (1000 * delay) / this.container.retina.reduceFactor;
|
|
}
|
|
if (this._lifeCount > 0 || this._immortal) {
|
|
this.prepareToDie();
|
|
}
|
|
}
|
|
resize() {
|
|
const initialPosition = this._initialPosition;
|
|
this.position =
|
|
initialPosition && isPointInside(initialPosition, this.container.canvas.size, Vector.origin)
|
|
? 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;
|
|
}
|
|
if (!this._startParticlesAdded) {
|
|
this._startParticlesAdded = true;
|
|
this.emitParticles(this.options.startCount);
|
|
}
|
|
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.options.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._engine.dispatchEvent("emitterPlay", {
|
|
container: this.container,
|
|
});
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
calcPosition() {
|
|
return calcPositionOrRandomFromSizeRanged({
|
|
size: this.container.canvas.size,
|
|
position: this.options.position,
|
|
});
|
|
}
|
|
destroy() {
|
|
this.emitters.removeEmitter(this);
|
|
this._engine.dispatchEvent("emitterDestroyed", {
|
|
container: this.container,
|
|
data: {
|
|
emitter: this,
|
|
},
|
|
});
|
|
}
|
|
emit() {
|
|
if (this._paused) {
|
|
return;
|
|
}
|
|
const quantity = getRangeValue(this.options.rate.quantity);
|
|
this.emitParticles(quantity);
|
|
}
|
|
emitParticles(quantity) {
|
|
var _a, _b, _c;
|
|
const position = this.getPosition(), size = this.getSize(), singleParticlesOptions = itemFromSingleOrMultiple(this._particlesOptions);
|
|
for (let i = 0; i < quantity; i++) {
|
|
const particlesOptions = deepExtend({}, singleParticlesOptions);
|
|
if (this.spawnColor) {
|
|
const hslAnimation = (_a = this.options.spawnColor) === null || _a === void 0 ? void 0 : _a.animation;
|
|
if (hslAnimation) {
|
|
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;
|
|
}
|
|
}
|
|
if (!position) {
|
|
return;
|
|
}
|
|
const pPosition = (_c = (_b = this._shape) === null || _b === void 0 ? void 0 : _b.randomPosition(position, size, this.fill)) !== null && _c !== void 0 ? _c : position;
|
|
this.container.particles.addParticle(pPosition, particlesOptions);
|
|
}
|
|
}
|
|
prepareToDie() {
|
|
var _a;
|
|
if (this._paused) {
|
|
return;
|
|
}
|
|
const duration = (_a = this.options.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;
|
|
}
|
|
}
|
|
setColorAnimation(animation, initValue, maxValue) {
|
|
var _a;
|
|
const container = this.container;
|
|
if (!animation.enable) {
|
|
return initValue;
|
|
}
|
|
const colorOffset = randomInRange(animation.offset), delay = getRangeValue(this.options.rate.delay), emitFactor = (1000 * delay) / container.retina.reduceFactor, colorSpeed = getRangeValue((_a = animation.speed) !== null && _a !== void 0 ? _a : 0);
|
|
return (initValue + (colorSpeed * container.fpsLimit) / emitFactor + colorOffset * 3.6) % maxValue;
|
|
}
|
|
}
|