@tsparticles/updater-out-modes
Version:
tsParticles particles out modes updater
365 lines (354 loc) • 21.6 kB
JavaScript
(function(g){g.__tsParticlesInternals=g.__tsParticlesInternals||{};g.__tsParticlesInternals.bundles=g.__tsParticlesInternals.bundles||{};g.__tsParticlesInternals.effects=g.__tsParticlesInternals.effects||{};g.__tsParticlesInternals.engine=g.__tsParticlesInternals.engine||{};g.__tsParticlesInternals.interactions=g.__tsParticlesInternals.interactions||{};g.__tsParticlesInternals.palettes=g.__tsParticlesInternals.palettes||{};g.__tsParticlesInternals.paths=g.__tsParticlesInternals.paths||{};g.__tsParticlesInternals.plugins=g.__tsParticlesInternals.plugins||{};g.__tsParticlesInternals.plugins=g.__tsParticlesInternals.plugins||{};g.__tsParticlesInternals.plugins.emittersShapes=g.__tsParticlesInternals.plugins.emittersShapes||{};g.__tsParticlesInternals.presets=g.__tsParticlesInternals.presets||{};g.__tsParticlesInternals.shapes=g.__tsParticlesInternals.shapes||{};g.__tsParticlesInternals.updaters=g.__tsParticlesInternals.updaters||{};g.__tsParticlesInternals.utils=g.__tsParticlesInternals.utils||{};g.__tsParticlesInternals.canvas=g.__tsParticlesInternals.canvas||{};g.__tsParticlesInternals.canvas=g.__tsParticlesInternals.canvas||{};g.__tsParticlesInternals.canvas.utils=g.__tsParticlesInternals.canvas.utils||{};g.__tsParticlesInternals.path=g.__tsParticlesInternals.path||{};g.__tsParticlesInternals.path=g.__tsParticlesInternals.path||{};g.__tsParticlesInternals.path.utils=g.__tsParticlesInternals.path.utils||{};var __tsProxyFactory=typeof Proxy!=="undefined"?function(obj){return new Proxy(obj,{get:function(target,key){if(!(key in target)){target[key]={};}return target[key];}});}:function(obj){return obj;};g.__tsParticlesInternals.bundles=__tsProxyFactory(g.__tsParticlesInternals.bundles);g.__tsParticlesInternals.effects=__tsProxyFactory(g.__tsParticlesInternals.effects);g.__tsParticlesInternals.interactions=__tsProxyFactory(g.__tsParticlesInternals.interactions);g.__tsParticlesInternals.palettes=__tsProxyFactory(g.__tsParticlesInternals.palettes);g.__tsParticlesInternals.paths=__tsProxyFactory(g.__tsParticlesInternals.paths);g.__tsParticlesInternals.plugins=__tsProxyFactory(g.__tsParticlesInternals.plugins);g.__tsParticlesInternals.plugins.emittersShapes=__tsProxyFactory(g.__tsParticlesInternals.plugins.emittersShapes);g.__tsParticlesInternals.presets=__tsProxyFactory(g.__tsParticlesInternals.presets);g.__tsParticlesInternals.shapes=__tsProxyFactory(g.__tsParticlesInternals.shapes);g.__tsParticlesInternals.updaters=__tsProxyFactory(g.__tsParticlesInternals.updaters);g.__tsParticlesInternals.utils=__tsProxyFactory(g.__tsParticlesInternals.utils);g.__tsParticlesInternals.canvas=__tsProxyFactory(g.__tsParticlesInternals.canvas);g.__tsParticlesInternals.path=__tsProxyFactory(g.__tsParticlesInternals.path);g.tsparticlesInternalExports=g.tsparticlesInternalExports||{};})(typeof globalThis!=="undefined"?globalThis:typeof window!=="undefined"?window:this);
/* Updater v4.1.1 */
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@tsparticles/engine')) :
typeof define === 'function' && define.amd ? define(['exports', '@tsparticles/engine'], factory) :
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory((global.__tsParticlesInternals = global.__tsParticlesInternals || {}, global.__tsParticlesInternals.updaters = global.__tsParticlesInternals.updaters || {}, global.__tsParticlesInternals.updaters.outModes = global.__tsParticlesInternals.updaters.outModes || {}), global.__tsParticlesInternals.engine));
})(this, (function (exports, engine) { 'use strict';
const minVelocity$3 = 0, boundsMin = 0;
function bounceHorizontal(data) {
if ((data.outMode !== engine.OutMode.bounce && data.outMode !== engine.OutMode.split) ||
(data.direction !== engine.OutModeDirection.left && data.direction !== engine.OutModeDirection.right)) {
return;
}
if (data.bounds.right < boundsMin && data.direction === engine.OutModeDirection.left) {
data.particle.position.x = data.size + data.offset.x;
}
else if (data.bounds.left > data.canvasSize.width && data.direction === engine.OutModeDirection.right) {
data.particle.position.x = data.canvasSize.width - data.size - data.offset.x;
}
const velocity = data.particle.velocity.x;
let bounced = false;
if (data.outOfCanvas &&
((data.direction === engine.OutModeDirection.right && velocity > minVelocity$3) ||
(data.direction === engine.OutModeDirection.left && velocity < minVelocity$3))) {
const newVelocity = engine.getRangeValue(data.particle.options.bounce.horizontal.value);
data.particle.velocity.x *= -newVelocity;
bounced = true;
}
if (!bounced) {
return;
}
const minPos = data.offset.x + data.size;
if (data.outOfCanvas && data.direction === engine.OutModeDirection.right) {
data.particle.position.x = data.canvasSize.width - minPos;
}
else if (data.outOfCanvas && data.direction === engine.OutModeDirection.left) {
data.particle.position.x = minPos;
}
if (data.outMode === engine.OutMode.split) {
data.particle.destroy();
}
}
function bounceVertical(data) {
if ((data.outMode !== engine.OutMode.bounce && data.outMode !== engine.OutMode.split) ||
(data.direction !== engine.OutModeDirection.bottom && data.direction !== engine.OutModeDirection.top)) {
return;
}
if (data.bounds.bottom < boundsMin && data.direction === engine.OutModeDirection.top) {
data.particle.position.y = data.size + data.offset.y;
}
else if (data.bounds.top > data.canvasSize.height && data.direction === engine.OutModeDirection.bottom) {
data.particle.position.y = data.canvasSize.height - data.size - data.offset.y;
}
const velocity = data.particle.velocity.y;
let bounced = false;
if (data.outOfCanvas &&
((data.direction === engine.OutModeDirection.bottom && velocity > minVelocity$3) ||
(data.direction === engine.OutModeDirection.top && velocity < minVelocity$3))) {
const newVelocity = engine.getRangeValue(data.particle.options.bounce.vertical.value);
data.particle.velocity.y *= -newVelocity;
bounced = true;
}
if (!bounced) {
return;
}
const minPos = data.offset.y + data.size;
if (data.outOfCanvas && data.direction === engine.OutModeDirection.bottom) {
data.particle.position.y = data.canvasSize.height - minPos;
}
else if (data.outOfCanvas && data.direction === engine.OutModeDirection.top) {
data.particle.position.y = minPos;
}
if (data.outMode === engine.OutMode.split) {
data.particle.destroy();
}
}
class BounceOutMode {
modes;
#container;
#particleBouncePlugins;
constructor(container) {
this.#container = container;
this.modes = [
engine.OutMode.bounce,
engine.OutMode.split,
];
this.#particleBouncePlugins = container.plugins.filter(p => p.particleBounce !== undefined);
}
update(particle, direction, delta, outMode) {
if (!this.modes.includes(outMode)) {
return;
}
const container = this.#container;
let handled = false;
for (const plugin of this.#particleBouncePlugins) {
handled = plugin.particleBounce?.(particle, delta, direction) ?? false;
if (handled) {
break;
}
}
if (handled) {
return;
}
const pos = particle.getPosition(), offset = particle.offset, size = particle.getRadius(), bounds = engine.calculateBounds(pos, size), canvasSize = container.canvas.size, outOfCanvas = !particle.isInsideCanvasForOutMode(outMode, direction);
bounceHorizontal({ particle, outMode, direction, bounds, canvasSize, offset, outOfCanvas, size });
bounceVertical({ particle, outMode, direction, bounds, canvasSize, offset, outOfCanvas, size });
}
}
const minVelocity$2 = 0;
class DestroyOutMode {
modes;
constructor(_container) {
this.modes = [engine.OutMode.destroy];
}
update(particle, direction, _delta, outMode) {
if (!this.modes.includes(outMode)) {
return;
}
switch (particle.outType) {
case engine.ParticleOutType.normal:
case engine.ParticleOutType.outside:
if (particle.isInsideCanvasForOutMode(outMode, direction)) {
return;
}
break;
case engine.ParticleOutType.inside: {
const { dx, dy } = engine.getDistances(particle.position, particle.moveCenter), { x: vx, y: vy } = particle.velocity;
if ((vx < minVelocity$2 && dx > particle.moveCenter.radius) ||
(vy < minVelocity$2 && dy > particle.moveCenter.radius) ||
(vx >= minVelocity$2 && dx < -particle.moveCenter.radius) ||
(vy >= minVelocity$2 && dy < -particle.moveCenter.radius)) {
return;
}
break;
}
}
particle.destroy(true);
}
}
const minVelocity$1 = 0;
class NoneOutMode {
modes;
#container;
constructor(container) {
this.#container = container;
this.modes = [engine.OutMode.none];
}
update(particle, direction, _delta, outMode) {
if (!this.modes.includes(outMode)) {
return;
}
if ((particle.options.move.distance.horizontal &&
(direction === engine.OutModeDirection.left || direction === engine.OutModeDirection.right)) ??
(particle.options.move.distance.vertical &&
(direction === engine.OutModeDirection.top || direction === engine.OutModeDirection.bottom))) {
return;
}
const gravityOptions = particle.options.move.gravity, container = this.#container, canvasSize = container.canvas.size, pRadius = particle.getRadius();
if (!gravityOptions.enable) {
if ((particle.velocity.y > minVelocity$1 && particle.position.y <= canvasSize.height + pRadius) ||
(particle.velocity.y < minVelocity$1 && particle.position.y >= -pRadius) ||
(particle.velocity.x > minVelocity$1 && particle.position.x <= canvasSize.width + pRadius) ||
(particle.velocity.x < minVelocity$1 && particle.position.x >= -pRadius)) {
return;
}
if (!engine.isPointInside(particle.position, container.canvas.size, engine.originPoint, pRadius, direction)) {
particle.destroy();
}
}
else {
const position = particle.position;
if ((!gravityOptions.inverse &&
position.y > canvasSize.height + pRadius &&
direction === engine.OutModeDirection.bottom) ||
(gravityOptions.inverse && position.y < -pRadius && direction === engine.OutModeDirection.top)) {
particle.destroy();
}
}
}
}
const minVelocity = 0, minDistance = 0, updateVector = engine.Vector.origin;
class OutOutMode {
modes;
#container;
constructor(container) {
this.#container = container;
this.modes = [engine.OutMode.out];
}
update(particle, direction, _delta, outMode) {
if (!this.modes.includes(outMode)) {
return;
}
const container = this.#container;
switch (particle.outType) {
case engine.ParticleOutType.inside: {
const { x: vx, y: vy } = particle.velocity;
updateVector.setTo(engine.originPoint);
updateVector.length = particle.moveCenter.radius;
updateVector.angle = particle.velocity.angle + Math.PI;
updateVector.addTo(particle.moveCenter);
const { dx, dy } = engine.getDistances(particle.position, updateVector);
if ((vx <= minVelocity && dx >= minDistance) ||
(vy <= minVelocity && dy >= minDistance) ||
(vx >= minVelocity && dx <= minDistance) ||
(vy >= minVelocity && dy <= minDistance)) {
return;
}
particle.position.x = Math.floor(engine.randomInRangeValue({
min: 0,
max: container.canvas.size.width,
}));
particle.position.y = Math.floor(engine.randomInRangeValue({
min: 0,
max: container.canvas.size.height,
}));
const { dx: newDx, dy: newDy } = engine.getDistances(particle.position, particle.moveCenter);
particle.direction = Math.atan2(-newDy, -newDx);
particle.velocity.angle = particle.direction;
particle.justWarped = true;
break;
}
default: {
if (particle.isInsideCanvasForOutMode(outMode, direction)) {
return;
}
switch (particle.outType) {
case engine.ParticleOutType.outside: {
particle.position.x =
Math.floor(engine.randomInRangeValue({
min: -particle.moveCenter.radius,
max: particle.moveCenter.radius,
})) + particle.moveCenter.x;
particle.position.y =
Math.floor(engine.randomInRangeValue({
min: -particle.moveCenter.radius,
max: particle.moveCenter.radius,
})) + particle.moveCenter.y;
const { dx, dy } = engine.getDistances(particle.position, particle.moveCenter);
if (particle.moveCenter.radius) {
particle.direction = Math.atan2(dy, dx);
particle.velocity.angle = particle.direction;
}
particle.justWarped = true;
break;
}
case engine.ParticleOutType.normal: {
const warp = particle.options.move.warp, canvasSize = container.canvas.size, newPos = {
bottom: canvasSize.height + particle.getRadius() + particle.offset.y,
left: -particle.getRadius() - particle.offset.x,
right: canvasSize.width + particle.getRadius() + particle.offset.x,
top: -particle.getRadius() - particle.offset.y,
}, sizeValue = particle.getRadius(), nextBounds = engine.calculateBounds(particle.position, sizeValue);
if (direction === engine.OutModeDirection.right && nextBounds.left > canvasSize.width + particle.offset.x) {
particle.position.x = newPos.left;
particle.initialPosition.x = particle.position.x;
if (!warp) {
particle.position.y = engine.getRandom() * canvasSize.height;
particle.initialPosition.y = particle.position.y;
}
particle.justWarped = true;
}
else if (direction === engine.OutModeDirection.left && nextBounds.right < -particle.offset.x) {
particle.position.x = newPos.right;
particle.initialPosition.x = particle.position.x;
if (!warp) {
particle.position.y = engine.getRandom() * canvasSize.height;
particle.initialPosition.y = particle.position.y;
}
particle.justWarped = true;
}
if (direction === engine.OutModeDirection.bottom && nextBounds.top > canvasSize.height + particle.offset.y) {
if (!warp) {
particle.position.x = engine.getRandom() * canvasSize.width;
particle.initialPosition.x = particle.position.x;
}
particle.position.y = newPos.top;
particle.initialPosition.y = particle.position.y;
particle.justWarped = true;
}
else if (direction === engine.OutModeDirection.top && nextBounds.bottom < -particle.offset.y) {
if (!warp) {
particle.position.x = engine.getRandom() * canvasSize.width;
particle.initialPosition.x = particle.position.x;
}
particle.position.y = newPos.bottom;
particle.initialPosition.y = particle.position.y;
particle.justWarped = true;
}
break;
}
}
break;
}
}
}
}
const checkOutMode = (outModes, outMode) => {
return (outModes.default === outMode ||
outModes.bottom === outMode ||
outModes.left === outMode ||
outModes.right === outMode ||
outModes.top === outMode);
};
class OutOfCanvasUpdater {
updaters;
#container;
constructor(container) {
this.#container = container;
this.updaters = new Map();
}
init(particle) {
this.#addUpdaterIfMissing(particle, engine.OutMode.bounce, container => new BounceOutMode(container));
this.#addUpdaterIfMissing(particle, engine.OutMode.out, container => new OutOutMode(container));
this.#addUpdaterIfMissing(particle, engine.OutMode.destroy, container => new DestroyOutMode(container));
this.#addUpdaterIfMissing(particle, engine.OutMode.none, container => new NoneOutMode(container));
}
isEnabled(particle) {
return !particle.destroyed && !particle.spawning;
}
update(particle, delta) {
const outModes = particle.options.move.outModes;
particle.justWarped = false;
this.#updateOutMode(particle, delta, outModes.bottom ?? outModes.default, engine.OutModeDirection.bottom);
this.#updateOutMode(particle, delta, outModes.left ?? outModes.default, engine.OutModeDirection.left);
this.#updateOutMode(particle, delta, outModes.right ?? outModes.default, engine.OutModeDirection.right);
this.#updateOutMode(particle, delta, outModes.top ?? outModes.default, engine.OutModeDirection.top);
}
#addUpdaterIfMissing = (particle, outMode, getUpdater) => {
const outModes = particle.options.move.outModes;
if (!this.updaters.has(outMode) && checkOutMode(outModes, outMode)) {
this.updaters.set(outMode, getUpdater(this.#container));
}
};
#updateOutMode = (particle, delta, outMode, direction) => {
for (const updater of this.updaters.values()) {
updater.update(particle, direction, delta, outMode);
}
};
}
async function loadOutModesUpdater(engine) {
engine.checkVersion("4.1.1");
await engine.pluginManager.register(e => {
e.pluginManager.addParticleUpdater("outModes", container => {
return Promise.resolve(new OutOfCanvasUpdater(container));
});
});
}
const globalObject = globalThis;
globalObject.__tsParticlesInternals = globalObject.__tsParticlesInternals ?? {};
globalObject.loadOutModesUpdater = loadOutModesUpdater;
exports.loadOutModesUpdater = loadOutModesUpdater;
}));
Object.assign(globalThis.window || globalThis, { loadOutModesUpdater: (globalThis.__tsParticlesInternals.updaters.outModes || {}).loadOutModesUpdater });
delete (globalThis.window || globalThis).tsparticlesInternalExports;