2023-02-17 11:06:01 +01:00

346 lines
17 KiB
JavaScript

(function (factory) {
if (typeof module === "object" && typeof module.exports === "object") {
var v = factory(require, exports);
if (v !== undefined) module.exports = v;
}
else if (typeof define === "function" && define.amd) {
define(["require", "exports", "../Utils/NumberUtils", "../Utils/Utils", "../Utils/ColorUtils", "../Options/Classes/Interactivity/Interactivity", "./Utils/Vector", "./Utils/Vector3d", "../Utils/CanvasUtils", "../Utils/OptionsUtils"], factory);
}
})(function (require, exports) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Particle = void 0;
const NumberUtils_1 = require("../Utils/NumberUtils");
const Utils_1 = require("../Utils/Utils");
const ColorUtils_1 = require("../Utils/ColorUtils");
const Interactivity_1 = require("../Options/Classes/Interactivity/Interactivity");
const Vector_1 = require("./Utils/Vector");
const Vector3d_1 = require("./Utils/Vector3d");
const CanvasUtils_1 = require("../Utils/CanvasUtils");
const OptionsUtils_1 = require("../Utils/OptionsUtils");
const fixOutMode = (data) => {
if (!(0, Utils_1.isInArray)(data.outMode, data.checkModes)) {
return;
}
if (data.coord > data.maxCoord - data.radius * 2) {
data.setCb(-data.radius);
}
else if (data.coord < data.radius * 2) {
data.setCb(data.radius);
}
};
class Particle {
constructor(engine, id, container, position, overrideOptions, group) {
this.container = container;
this._engine = engine;
this.init(id, position, overrideOptions, group);
}
destroy(override) {
var _a;
if (this.unbreakable || this.destroyed) {
return;
}
this.destroyed = true;
this.bubble.inRange = false;
this.slow.inRange = false;
for (const [, plugin] of this.container.plugins) {
if (plugin.particleDestroyed) {
plugin.particleDestroyed(this, override);
}
}
for (const updater of this.container.particles.updaters) {
if (updater.particleDestroyed) {
updater.particleDestroyed(this, override);
}
}
(_a = this.pathGenerator) === null || _a === void 0 ? void 0 : _a.reset(this);
}
draw(delta) {
const container = this.container;
for (const [, plugin] of container.plugins) {
container.canvas.drawParticlePlugin(plugin, this, delta);
}
container.canvas.drawParticle(this, delta);
}
getFillColor() {
var _a;
return this._getRollColor((_a = this.bubble.color) !== null && _a !== void 0 ? _a : (0, ColorUtils_1.getHslFromAnimation)(this.color));
}
getMass() {
return (this.getRadius() ** 2 * Math.PI) / 2;
}
getPosition() {
return {
x: this.position.x + this.offset.x,
y: this.position.y + this.offset.y,
z: this.position.z,
};
}
getRadius() {
var _a;
return (_a = this.bubble.radius) !== null && _a !== void 0 ? _a : this.size.value;
}
getStrokeColor() {
var _a;
return this._getRollColor((_a = this.bubble.color) !== null && _a !== void 0 ? _a : (0, ColorUtils_1.getHslFromAnimation)(this.strokeColor));
}
init(id, position, overrideOptions, group) {
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
const container = this.container, engine = this._engine;
this.id = id;
this.group = group;
this.fill = true;
this.pathRotation = false;
this.close = true;
this.lastPathTime = 0;
this.destroyed = false;
this.unbreakable = false;
this.rotation = 0;
this.misplaced = false;
this.retina = {
maxDistance: {},
};
this.outType = "normal";
this.ignoresResizeRatio = true;
const pxRatio = container.retina.pixelRatio, mainOptions = container.actualOptions, particlesOptions = (0, OptionsUtils_1.loadParticlesOptions)(this._engine, container, mainOptions.particles), shapeType = particlesOptions.shape.type, { reduceDuplicates } = particlesOptions;
this.shape = (0, Utils_1.itemFromSingleOrMultiple)(shapeType, this.id, reduceDuplicates);
const shapeOptions = particlesOptions.shape;
if (overrideOptions && overrideOptions.shape && overrideOptions.shape.type) {
const overrideShapeType = overrideOptions.shape.type, shape = (0, Utils_1.itemFromSingleOrMultiple)(overrideShapeType, this.id, reduceDuplicates);
if (shape) {
this.shape = shape;
shapeOptions.load(overrideOptions.shape);
}
}
this.shapeData = this._loadShapeData(shapeOptions, reduceDuplicates);
particlesOptions.load(overrideOptions);
particlesOptions.load((_a = this.shapeData) === null || _a === void 0 ? void 0 : _a.particles);
this.interactivity = new Interactivity_1.Interactivity(engine, container);
this.interactivity.load(container.actualOptions.interactivity);
this.interactivity.load(particlesOptions.interactivity);
this.fill = (_c = (_b = this.shapeData) === null || _b === void 0 ? void 0 : _b.fill) !== null && _c !== void 0 ? _c : this.fill;
this.close = (_e = (_d = this.shapeData) === null || _d === void 0 ? void 0 : _d.close) !== null && _e !== void 0 ? _e : this.close;
this.options = particlesOptions;
const pathOptions = this.options.move.path;
this.pathDelay = (0, NumberUtils_1.getValue)(pathOptions.delay) * 1000;
if (pathOptions.generator) {
this.pathGenerator = this._engine.plugins.getPathGenerator(pathOptions.generator);
if (this.pathGenerator && container.addPath(pathOptions.generator, this.pathGenerator)) {
this.pathGenerator.init(container);
}
}
const zIndexValue = (0, NumberUtils_1.getRangeValue)(this.options.zIndex.value);
container.retina.initParticle(this);
const sizeOptions = this.options.size, sizeRange = sizeOptions.value, sizeAnimation = sizeOptions.animation;
this.size = {
enable: sizeOptions.animation.enable,
value: (0, NumberUtils_1.getRangeValue)(sizeOptions.value) * container.retina.pixelRatio,
max: (0, NumberUtils_1.getRangeMax)(sizeRange) * pxRatio,
min: (0, NumberUtils_1.getRangeMin)(sizeRange) * pxRatio,
loops: 0,
maxLoops: (0, NumberUtils_1.getRangeValue)(sizeOptions.animation.count),
};
if (sizeAnimation.enable) {
this.size.status = "increasing";
this.size.decay = 1 - (0, NumberUtils_1.getRangeValue)(sizeAnimation.decay);
switch (sizeAnimation.startValue) {
case "min":
this.size.value = this.size.min;
this.size.status = "increasing";
break;
case "random":
this.size.value = (0, NumberUtils_1.randomInRange)(this.size);
this.size.status = (0, NumberUtils_1.getRandom)() >= 0.5 ? "increasing" : "decreasing";
break;
case "max":
default:
this.size.value = this.size.max;
this.size.status = "decreasing";
break;
}
}
this.size.initialValue = this.size.value;
this.bubble = {
inRange: false,
};
this.slow = {
inRange: false,
factor: 1,
};
this.position = this._calcPosition(container, position, (0, NumberUtils_1.clamp)(zIndexValue, 0, container.zLayers));
this.initialPosition = this.position.copy();
const canvasSize = container.canvas.size, moveCenter = Object.assign({}, this.options.move.center), isCenterPercent = moveCenter.mode === "percent";
this.moveCenter = {
x: moveCenter.x * (isCenterPercent ? canvasSize.width / 100 : 1),
y: moveCenter.y * (isCenterPercent ? canvasSize.height / 100 : 1),
radius: (_f = this.options.move.center.radius) !== null && _f !== void 0 ? _f : 0,
mode: (_g = this.options.move.center.mode) !== null && _g !== void 0 ? _g : "percent",
};
this.direction = (0, NumberUtils_1.getParticleDirectionAngle)(this.options.move.direction, this.position, this.moveCenter);
switch (this.options.move.direction) {
case "inside":
this.outType = "inside";
break;
case "outside":
this.outType = "outside";
break;
}
this.initialVelocity = this._calculateVelocity();
this.velocity = this.initialVelocity.copy();
this.moveDecay = 1 - (0, NumberUtils_1.getRangeValue)(this.options.move.decay);
this.offset = Vector_1.Vector.origin;
const particles = container.particles;
particles.needsSort = particles.needsSort || particles.lastZIndex < this.position.z;
particles.lastZIndex = this.position.z;
this.zIndexFactor = this.position.z / container.zLayers;
this.sides = 24;
let drawer = container.drawers.get(this.shape);
if (!drawer) {
drawer = this._engine.plugins.getShapeDrawer(this.shape);
if (drawer) {
container.drawers.set(this.shape, drawer);
}
}
if (drawer === null || drawer === void 0 ? void 0 : drawer.loadShape) {
drawer === null || drawer === void 0 ? void 0 : drawer.loadShape(this);
}
const sideCountFunc = drawer === null || drawer === void 0 ? void 0 : drawer.getSidesCount;
if (sideCountFunc) {
this.sides = sideCountFunc(this);
}
this.spawning = false;
this.shadowColor = (0, ColorUtils_1.rangeColorToRgb)(this.options.shadow.color);
for (const updater of container.particles.updaters) {
updater.init(this);
}
for (const mover of container.particles.movers) {
(_h = mover.init) === null || _h === void 0 ? void 0 : _h.call(mover, this);
}
if (drawer === null || drawer === void 0 ? void 0 : drawer.particleInit) {
drawer.particleInit(container, this);
}
for (const [, plugin] of container.plugins) {
(_j = plugin.particleCreated) === null || _j === void 0 ? void 0 : _j.call(plugin, this);
}
}
isInsideCanvas() {
const radius = this.getRadius(), canvasSize = this.container.canvas.size;
return (this.position.x >= -radius &&
this.position.y >= -radius &&
this.position.y <= canvasSize.height + radius &&
this.position.x <= canvasSize.width + radius);
}
isVisible() {
return !this.destroyed && !this.spawning && this.isInsideCanvas();
}
reset() {
var _a;
for (const updater of this.container.particles.updaters) {
(_a = updater.reset) === null || _a === void 0 ? void 0 : _a.call(updater, this);
}
}
_calcPosition(container, position, zIndex, tryCount = 0) {
var _a, _b, _c, _d;
for (const [, plugin] of container.plugins) {
const pluginPos = plugin.particlePosition !== undefined ? plugin.particlePosition(position, this) : undefined;
if (pluginPos !== undefined) {
return Vector3d_1.Vector3d.create(pluginPos.x, pluginPos.y, zIndex);
}
}
const canvasSize = container.canvas.size, exactPosition = (0, NumberUtils_1.calcExactPositionOrRandomFromSize)({
size: canvasSize,
position: position,
}), pos = Vector3d_1.Vector3d.create(exactPosition.x, exactPosition.y, zIndex), radius = this.getRadius(), outModes = this.options.move.outModes, fixHorizontal = (outMode) => {
fixOutMode({
outMode,
checkModes: ["bounce", "bounce-horizontal"],
coord: pos.x,
maxCoord: container.canvas.size.width,
setCb: (value) => (pos.x += value),
radius,
});
}, fixVertical = (outMode) => {
fixOutMode({
outMode,
checkModes: ["bounce", "bounce-vertical"],
coord: pos.y,
maxCoord: container.canvas.size.height,
setCb: (value) => (pos.y += value),
radius,
});
};
fixHorizontal((_a = outModes.left) !== null && _a !== void 0 ? _a : outModes.default);
fixHorizontal((_b = outModes.right) !== null && _b !== void 0 ? _b : outModes.default);
fixVertical((_c = outModes.top) !== null && _c !== void 0 ? _c : outModes.default);
fixVertical((_d = outModes.bottom) !== null && _d !== void 0 ? _d : outModes.default);
if (this._checkOverlap(pos, tryCount)) {
return this._calcPosition(container, undefined, zIndex, tryCount + 1);
}
return pos;
}
_calculateVelocity() {
const baseVelocity = (0, NumberUtils_1.getParticleBaseVelocity)(this.direction), res = baseVelocity.copy(), moveOptions = this.options.move;
if (moveOptions.direction === "inside" || moveOptions.direction === "outside") {
return res;
}
const rad = (Math.PI / 180) * (0, NumberUtils_1.getRangeValue)(moveOptions.angle.value), radOffset = (Math.PI / 180) * (0, NumberUtils_1.getRangeValue)(moveOptions.angle.offset), range = {
left: radOffset - rad / 2,
right: radOffset + rad / 2,
};
if (!moveOptions.straight) {
res.angle += (0, NumberUtils_1.randomInRange)((0, NumberUtils_1.setRangeValue)(range.left, range.right));
}
if (moveOptions.random && typeof moveOptions.speed === "number") {
res.length *= (0, NumberUtils_1.getRandom)();
}
return res;
}
_checkOverlap(pos, tryCount = 0) {
const collisionsOptions = this.options.collisions, radius = this.getRadius();
if (!collisionsOptions.enable) {
return false;
}
const overlapOptions = collisionsOptions.overlap;
if (overlapOptions.enable) {
return false;
}
const retries = overlapOptions.retries;
if (retries >= 0 && tryCount > retries) {
throw new Error("Particle is overlapping and can't be placed");
}
let overlaps = false;
for (const particle of this.container.particles.array) {
if ((0, NumberUtils_1.getDistance)(pos, particle.position) < radius + particle.getRadius()) {
overlaps = true;
break;
}
}
return overlaps;
}
_getRollColor(color) {
var _a;
if (!color || !this.roll || (!this.backColor && !this.roll.alter)) {
return color;
}
const backFactor = this.roll.horizontal && this.roll.vertical ? 2 : 1, backSum = this.roll.horizontal ? Math.PI / 2 : 0, rolled = Math.floor((((_a = this.roll.angle) !== null && _a !== void 0 ? _a : 0) + backSum) / (Math.PI / backFactor)) % 2;
if (!rolled) {
return color;
}
if (this.backColor) {
return this.backColor;
}
if (this.roll.alter) {
return (0, CanvasUtils_1.alterHsl)(color, this.roll.alter.type, this.roll.alter.value);
}
return color;
}
_loadShapeData(shapeOptions, reduceDuplicates) {
const shapeData = shapeOptions.options[this.shape];
if (shapeData) {
return (0, Utils_1.deepExtend)({}, (0, Utils_1.itemFromSingleOrMultiple)(shapeData, this.id, reduceDuplicates));
}
}
}
exports.Particle = Particle;
});