Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@tsparticles/interaction-external-bubble

Package Overview
Dependencies
Maintainers
2
Versions
24
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@tsparticles/interaction-external-bubble - npm Package Compare versions

Comparing version 3.0.0-alpha.1 to 3.0.0-beta.0

browser/Enums.js

445

browser/Bubbler.js

@@ -1,16 +0,209 @@

import { Circle, ExternalInteractorBase, Rectangle, clamp, colorMix, divMode, divModeExecute, getDistance, getRangeMax, isDivModeEnabled, isInArray, itemFromSingleOrMultiple, mouseLeaveEvent, mouseMoveEvent, rangeColorToHsl, rgbToHsl, } from "@tsparticles/engine";
import { Circle, ExternalInteractorBase, Rectangle, colorMix, divMode, divModeExecute, getDistance, getRangeMax, isDivModeEnabled, isInArray, itemFromSingleOrMultiple, mouseLeaveEvent, mouseMoveEvent, rangeColorToHsl, rgbToHsl, } from "@tsparticles/engine";
import { Bubble } from "./Options/Classes/Bubble";
function calculateBubbleValue(particleValue, modeValue, optionsValue, ratio) {
if (modeValue >= optionsValue) {
const value = particleValue + (modeValue - optionsValue) * ratio;
return clamp(value, particleValue, modeValue);
}
else if (modeValue < optionsValue) {
const value = particleValue - (optionsValue - modeValue) * ratio;
return clamp(value, modeValue, particleValue);
}
}
import { calculateBubbleValue } from "./Utils";
export class Bubbler extends ExternalInteractorBase {
constructor(container) {
super(container);
this._clickBubble = () => {
const container = this.container, options = container.actualOptions, mouseClickPos = container.interactivity.mouse.clickPosition, bubbleOptions = options.interactivity.modes.bubble;
if (!bubbleOptions || !mouseClickPos) {
return;
}
if (!container.bubble) {
container.bubble = {};
}
const distance = container.retina.bubbleModeDistance;
if (!distance || distance < 0) {
return;
}
const query = container.particles.quadTree.queryCircle(mouseClickPos, distance, (p) => this.isEnabled(p)), { bubble } = container;
for (const particle of query) {
if (!bubble.clicking) {
continue;
}
particle.bubble.inRange = !bubble.durationEnd;
const pos = particle.getPosition(), distMouse = getDistance(pos, mouseClickPos), timeSpent = (new Date().getTime() - (container.interactivity.mouse.clickTime || 0)) / 1000;
if (timeSpent > bubbleOptions.duration) {
bubble.durationEnd = true;
}
if (timeSpent > bubbleOptions.duration * 2) {
bubble.clicking = false;
bubble.durationEnd = false;
}
const sizeData = {
bubbleObj: {
optValue: container.retina.bubbleModeSize,
value: particle.bubble.radius,
},
particlesObj: {
optValue: getRangeMax(particle.options.size.value) * container.retina.pixelRatio,
value: particle.size.value,
},
type: "size",
};
this._process(particle, distMouse, timeSpent, sizeData);
const opacityData = {
bubbleObj: {
optValue: bubbleOptions.opacity,
value: particle.bubble.opacity,
},
particlesObj: {
optValue: getRangeMax(particle.options.opacity.value),
value: particle.opacity?.value ?? 1,
},
type: "opacity",
};
this._process(particle, distMouse, timeSpent, opacityData);
if (!bubble.durationEnd && distMouse <= distance) {
this._hoverBubbleColor(particle, distMouse);
}
else {
delete particle.bubble.color;
}
}
};
this._hoverBubble = () => {
const container = this.container, mousePos = container.interactivity.mouse.position, distance = container.retina.bubbleModeDistance;
if (!distance || distance < 0 || mousePos === undefined) {
return;
}
const query = container.particles.quadTree.queryCircle(mousePos, distance, (p) => this.isEnabled(p));
for (const particle of query) {
particle.bubble.inRange = true;
const pos = particle.getPosition(), pointDistance = getDistance(pos, mousePos), ratio = 1 - pointDistance / distance;
if (pointDistance <= distance) {
if (ratio >= 0 && container.interactivity.status === mouseMoveEvent) {
this._hoverBubbleSize(particle, ratio);
this._hoverBubbleOpacity(particle, ratio);
this._hoverBubbleColor(particle, ratio);
}
}
else {
this.reset(particle);
}
if (container.interactivity.status === mouseLeaveEvent) {
this.reset(particle);
}
}
};
this._hoverBubbleColor = (particle, ratio, divBubble) => {
const options = this.container.actualOptions, bubbleOptions = divBubble ?? options.interactivity.modes.bubble;
if (!bubbleOptions) {
return;
}
if (!particle.bubble.finalColor) {
const modeColor = bubbleOptions.color;
if (!modeColor) {
return;
}
const bubbleColor = itemFromSingleOrMultiple(modeColor);
particle.bubble.finalColor = rangeColorToHsl(bubbleColor);
}
if (!particle.bubble.finalColor) {
return;
}
if (bubbleOptions.mix) {
particle.bubble.color = undefined;
const pColor = particle.getFillColor();
particle.bubble.color = pColor
? rgbToHsl(colorMix(pColor, particle.bubble.finalColor, 1 - ratio, ratio))
: particle.bubble.finalColor;
}
else {
particle.bubble.color = particle.bubble.finalColor;
}
};
this._hoverBubbleOpacity = (particle, ratio, divBubble) => {
const container = this.container, options = container.actualOptions, modeOpacity = divBubble?.opacity ?? options.interactivity.modes.bubble?.opacity;
if (!modeOpacity) {
return;
}
const optOpacity = particle.options.opacity.value, pOpacity = particle.opacity?.value ?? 1, opacity = calculateBubbleValue(pOpacity, modeOpacity, getRangeMax(optOpacity), ratio);
if (opacity !== undefined) {
particle.bubble.opacity = opacity;
}
};
this._hoverBubbleSize = (particle, ratio, divBubble) => {
const container = this.container, modeSize = divBubble?.size ? divBubble.size * container.retina.pixelRatio : container.retina.bubbleModeSize;
if (modeSize === undefined) {
return;
}
const optSize = getRangeMax(particle.options.size.value) * container.retina.pixelRatio, pSize = particle.size.value, size = calculateBubbleValue(pSize, modeSize, optSize, ratio);
if (size !== undefined) {
particle.bubble.radius = size;
}
};
this._process = (particle, distMouse, timeSpent, data) => {
const container = this.container, bubbleParam = data.bubbleObj.optValue, options = container.actualOptions, bubbleOptions = options.interactivity.modes.bubble;
if (!bubbleOptions || bubbleParam === undefined) {
return;
}
const bubbleDuration = bubbleOptions.duration, bubbleDistance = container.retina.bubbleModeDistance, particlesParam = data.particlesObj.optValue, pObjBubble = data.bubbleObj.value, pObj = data.particlesObj.value || 0, type = data.type;
if (!bubbleDistance || bubbleDistance < 0 || bubbleParam === particlesParam) {
return;
}
if (!container.bubble) {
container.bubble = {};
}
if (container.bubble.durationEnd) {
if (pObjBubble) {
if (type === "size") {
delete particle.bubble.radius;
}
if (type === "opacity") {
delete particle.bubble.opacity;
}
}
}
else {
if (distMouse <= bubbleDistance) {
const obj = pObjBubble ?? pObj;
if (obj !== bubbleParam) {
const value = pObj - (timeSpent * (pObj - bubbleParam)) / bubbleDuration;
if (type === "size") {
particle.bubble.radius = value;
}
if (type === "opacity") {
particle.bubble.opacity = value;
}
}
}
else {
if (type === "size") {
delete particle.bubble.radius;
}
if (type === "opacity") {
delete particle.bubble.opacity;
}
}
}
};
this._singleSelectorHover = (delta, selector, div) => {
const container = this.container, selectors = document.querySelectorAll(selector), bubble = container.actualOptions.interactivity.modes.bubble;
if (!bubble || !selectors.length) {
return;
}
selectors.forEach((item) => {
const elem = item, pxRatio = container.retina.pixelRatio, pos = {
x: (elem.offsetLeft + elem.offsetWidth / 2) * pxRatio,
y: (elem.offsetTop + elem.offsetHeight / 2) * pxRatio,
}, repulseRadius = (elem.offsetWidth / 2) * pxRatio, area = div.type === "circle"
? new Circle(pos.x, pos.y, repulseRadius)
: new Rectangle(elem.offsetLeft * pxRatio, elem.offsetTop * pxRatio, elem.offsetWidth * pxRatio, elem.offsetHeight * pxRatio), query = container.particles.quadTree.query(area, (p) => this.isEnabled(p));
for (const particle of query) {
if (!area.contains(particle.getPosition())) {
continue;
}
particle.bubble.inRange = true;
const divs = bubble.divs, divBubble = divMode(divs, elem);
if (!particle.bubble.div || particle.bubble.div !== elem) {
this.clear(particle, delta, true);
particle.bubble.div = elem;
}
this._hoverBubbleSize(particle, 1, divBubble);
this._hoverBubbleOpacity(particle, 1, divBubble);
this._hoverBubbleColor(particle, 1, divBubble);
}
});
};
if (!container.bubble) {

@@ -51,20 +244,17 @@ container.bubble = {};

if (hoverEnabled && isInArray("bubble", hoverMode)) {
this.hoverBubble(delta);
this._hoverBubble();
}
else if (clickEnabled && isInArray("bubble", clickMode)) {
this.clickBubble(delta);
this._clickBubble();
}
else {
divModeExecute("bubble", divs, (selector, div) => this.singleSelectorHover(delta, selector, div));
divModeExecute("bubble", divs, (selector, div) => this._singleSelectorHover(delta, selector, div));
}
}
isEnabled(particle) {
var _a;
const container = this.container, options = container.actualOptions, mouse = container.interactivity.mouse, events = ((_a = particle === null || particle === void 0 ? void 0 : particle.interactivity) !== null && _a !== void 0 ? _a : options.interactivity).events, divs = events.onDiv, divBubble = isDivModeEnabled("bubble", divs);
if (!(divBubble || (events.onHover.enable && mouse.position) || (events.onClick.enable && mouse.clickPosition))) {
const container = this.container, options = container.actualOptions, mouse = container.interactivity.mouse, events = (particle?.interactivity ?? options.interactivity).events, { onClick, onDiv, onHover } = events, divBubble = isDivModeEnabled("bubble", onDiv);
if (!(divBubble || (onHover.enable && mouse.position) || (onClick.enable && mouse.clickPosition))) {
return false;
}
const hoverMode = events.onHover.mode;
const clickMode = events.onClick.mode;
return isInArray("bubble", hoverMode) || isInArray("bubble", clickMode) || divBubble;
return isInArray("bubble", onHover.mode) || isInArray("bubble", onClick.mode) || divBubble;
}

@@ -76,3 +266,3 @@ loadModeOptions(options, ...sources) {

for (const source of sources) {
options.bubble.load(source === null || source === void 0 ? void 0 : source.bubble);
options.bubble.load(source?.bubble);
}

@@ -83,215 +273,2 @@ }

}
clickBubble(delta) {
var _a, _b;
const container = this.container, options = container.actualOptions, mouseClickPos = container.interactivity.mouse.clickPosition, bubble = options.interactivity.modes.bubble;
if (!bubble || !mouseClickPos) {
return;
}
if (!container.bubble) {
container.bubble = {};
}
const distance = container.retina.bubbleModeDistance;
if (!distance || distance < 0) {
return;
}
const query = container.particles.quadTree.queryCircle(mouseClickPos, distance, (p) => this.isEnabled(p));
for (const particle of query) {
if (!container.bubble.clicking) {
continue;
}
particle.bubble.inRange = !container.bubble.durationEnd;
const pos = particle.getPosition(), distMouse = getDistance(pos, mouseClickPos), timeSpent = (new Date().getTime() - (container.interactivity.mouse.clickTime || 0)) / 1000;
if (timeSpent > bubble.duration) {
container.bubble.durationEnd = true;
}
if (timeSpent > bubble.duration * 2) {
container.bubble.clicking = false;
container.bubble.durationEnd = false;
}
const sizeData = {
bubbleObj: {
optValue: container.retina.bubbleModeSize,
value: particle.bubble.radius,
},
particlesObj: {
optValue: getRangeMax(particle.options.size.value) * container.retina.pixelRatio,
value: particle.size.value,
},
type: "size",
};
this.process(particle, distMouse, timeSpent, sizeData);
const opacityData = {
bubbleObj: {
optValue: bubble.opacity,
value: particle.bubble.opacity,
},
particlesObj: {
optValue: getRangeMax(particle.options.opacity.value),
value: (_b = (_a = particle.opacity) === null || _a === void 0 ? void 0 : _a.value) !== null && _b !== void 0 ? _b : 1,
},
type: "opacity",
};
this.process(particle, distMouse, timeSpent, opacityData);
if (!container.bubble.durationEnd) {
if (distMouse <= distance) {
this.hoverBubbleColor(particle, distMouse);
}
else {
delete particle.bubble.color;
}
}
else {
delete particle.bubble.color;
}
}
}
hoverBubble(delta) {
const container = this.container, mousePos = container.interactivity.mouse.position, distance = container.retina.bubbleModeDistance;
if (!distance || distance < 0 || mousePos === undefined) {
return;
}
const query = container.particles.quadTree.queryCircle(mousePos, distance, (p) => this.isEnabled(p));
for (const particle of query) {
particle.bubble.inRange = true;
const pos = particle.getPosition(), pointDistance = getDistance(pos, mousePos), ratio = 1 - pointDistance / distance;
if (pointDistance <= distance) {
if (ratio >= 0 && container.interactivity.status === mouseMoveEvent) {
this.hoverBubbleSize(particle, ratio);
this.hoverBubbleOpacity(particle, ratio);
this.hoverBubbleColor(particle, ratio);
}
}
else {
this.reset(particle);
}
if (container.interactivity.status === mouseLeaveEvent) {
this.reset(particle);
}
}
}
hoverBubbleColor(particle, ratio, divBubble) {
const options = this.container.actualOptions;
const bubbleOptions = divBubble !== null && divBubble !== void 0 ? divBubble : options.interactivity.modes.bubble;
if (!bubbleOptions) {
return;
}
if (!particle.bubble.finalColor) {
const modeColor = bubbleOptions.color;
if (!modeColor) {
return;
}
const bubbleColor = itemFromSingleOrMultiple(modeColor);
particle.bubble.finalColor = rangeColorToHsl(bubbleColor);
}
if (!particle.bubble.finalColor) {
return;
}
if (bubbleOptions.mix) {
particle.bubble.color = undefined;
const pColor = particle.getFillColor();
particle.bubble.color = pColor
? rgbToHsl(colorMix(pColor, particle.bubble.finalColor, 1 - ratio, ratio))
: particle.bubble.finalColor;
}
else {
particle.bubble.color = particle.bubble.finalColor;
}
}
hoverBubbleOpacity(particle, ratio, divBubble) {
var _a, _b, _c, _d;
const container = this.container, options = container.actualOptions, modeOpacity = (_a = divBubble === null || divBubble === void 0 ? void 0 : divBubble.opacity) !== null && _a !== void 0 ? _a : (_b = options.interactivity.modes.bubble) === null || _b === void 0 ? void 0 : _b.opacity;
if (!modeOpacity) {
return;
}
const optOpacity = particle.options.opacity.value;
const pOpacity = (_d = (_c = particle.opacity) === null || _c === void 0 ? void 0 : _c.value) !== null && _d !== void 0 ? _d : 1;
const opacity = calculateBubbleValue(pOpacity, modeOpacity, getRangeMax(optOpacity), ratio);
if (opacity !== undefined) {
particle.bubble.opacity = opacity;
}
}
hoverBubbleSize(particle, ratio, divBubble) {
const container = this.container, modeSize = (divBubble === null || divBubble === void 0 ? void 0 : divBubble.size) ? divBubble.size * container.retina.pixelRatio : container.retina.bubbleModeSize;
if (modeSize === undefined) {
return;
}
const optSize = getRangeMax(particle.options.size.value) * container.retina.pixelRatio;
const pSize = particle.size.value;
const size = calculateBubbleValue(pSize, modeSize, optSize, ratio);
if (size !== undefined) {
particle.bubble.radius = size;
}
}
process(particle, distMouse, timeSpent, data) {
const container = this.container, bubbleParam = data.bubbleObj.optValue, options = container.actualOptions, bubble = options.interactivity.modes.bubble;
if (!bubble || bubbleParam === undefined) {
return;
}
const bubbleDuration = bubble.duration, bubbleDistance = container.retina.bubbleModeDistance, particlesParam = data.particlesObj.optValue, pObjBubble = data.bubbleObj.value, pObj = data.particlesObj.value || 0, type = data.type;
if (!bubbleDistance || bubbleDistance < 0 || bubbleParam === particlesParam) {
return;
}
if (!container.bubble) {
container.bubble = {};
}
if (!container.bubble.durationEnd) {
if (distMouse <= bubbleDistance) {
const obj = pObjBubble !== null && pObjBubble !== void 0 ? pObjBubble : pObj;
if (obj !== bubbleParam) {
const value = pObj - (timeSpent * (pObj - bubbleParam)) / bubbleDuration;
if (type === "size") {
particle.bubble.radius = value;
}
if (type === "opacity") {
particle.bubble.opacity = value;
}
}
}
else {
if (type === "size") {
delete particle.bubble.radius;
}
if (type === "opacity") {
delete particle.bubble.opacity;
}
}
}
else if (pObjBubble) {
if (type === "size") {
delete particle.bubble.radius;
}
if (type === "opacity") {
delete particle.bubble.opacity;
}
}
}
singleSelectorHover(delta, selector, div) {
const container = this.container, selectors = document.querySelectorAll(selector), bubble = container.actualOptions.interactivity.modes.bubble;
if (!bubble || !selectors.length) {
return;
}
selectors.forEach((item) => {
const elem = item, pxRatio = container.retina.pixelRatio, pos = {
x: (elem.offsetLeft + elem.offsetWidth / 2) * pxRatio,
y: (elem.offsetTop + elem.offsetHeight / 2) * pxRatio,
}, repulseRadius = (elem.offsetWidth / 2) * pxRatio, area = div.type === "circle"
? new Circle(pos.x, pos.y, repulseRadius)
: new Rectangle(elem.offsetLeft * pxRatio, elem.offsetTop * pxRatio, elem.offsetWidth * pxRatio, elem.offsetHeight * pxRatio), query = container.particles.quadTree.query(area, (p) => this.isEnabled(p));
for (const particle of query) {
if (!area.contains(particle.getPosition())) {
continue;
}
particle.bubble.inRange = true;
const divs = bubble.divs;
const divBubble = divMode(divs, elem);
if (!particle.bubble.div || particle.bubble.div !== elem) {
this.clear(particle, delta, true);
particle.bubble.div = elem;
}
this.hoverBubbleSize(particle, 1, divBubble);
this.hoverBubbleOpacity(particle, 1, divBubble);
this.hoverBubbleColor(particle, 1, divBubble);
}
});
}
}
import { Bubbler } from "./Bubbler";
export async function loadExternalBubbleInteraction(engine) {
await engine.addInteractor("externalBubble", (container) => new Bubbler(container));
export async function loadExternalBubbleInteraction(engine, refresh = true) {
await engine.addInteractor("externalBubble", (container) => new Bubbler(container), refresh);
}

@@ -5,0 +5,0 @@ export * from "./Options/Classes/BubbleBase";

@@ -0,4 +1,4 @@

import { executeOnSingleOrMultiple, } from "@tsparticles/engine";
import { BubbleBase } from "./BubbleBase";
import { BubbleDiv } from "./BubbleDiv";
import { executeOnSingleOrMultiple } from "@tsparticles/engine";
export class Bubble extends BubbleBase {

@@ -5,0 +5,0 @@ load(data) {

@@ -1,2 +0,2 @@

import { OptionsColor, executeOnSingleOrMultiple } from "@tsparticles/engine";
import { OptionsColor, executeOnSingleOrMultiple, isArray, } from "@tsparticles/engine";
export class BubbleBase {

@@ -25,3 +25,3 @@ constructor() {

if (data.color !== undefined) {
const sourceColor = this.color instanceof Array ? undefined : this.color;
const sourceColor = isArray(this.color) ? undefined : this.color;
this.color = executeOnSingleOrMultiple(data.color, (color) => {

@@ -28,0 +28,0 @@ return OptionsColor.create(sourceColor, color);

import { BubbleBase } from "./BubbleBase";
import { executeOnSingleOrMultiple } from "@tsparticles/engine";
export class BubbleDiv extends BubbleBase {

@@ -8,8 +7,2 @@ constructor() {

}
get ids() {
return executeOnSingleOrMultiple(this.selectors, (t) => t.replace("#", ""));
}
set ids(value) {
this.selectors = executeOnSingleOrMultiple(value, (t) => `#${t}`);
}
load(data) {

@@ -20,5 +13,2 @@ super.load(data);

}
if (data.ids !== undefined) {
this.ids = data.ids;
}
if (data.selectors !== undefined) {

@@ -25,0 +15,0 @@ this.selectors = data.selectors;

"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });

@@ -15,15 +6,208 @@ exports.Bubbler = void 0;

const Bubble_1 = require("./Options/Classes/Bubble");
function calculateBubbleValue(particleValue, modeValue, optionsValue, ratio) {
if (modeValue >= optionsValue) {
const value = particleValue + (modeValue - optionsValue) * ratio;
return (0, engine_1.clamp)(value, particleValue, modeValue);
}
else if (modeValue < optionsValue) {
const value = particleValue - (optionsValue - modeValue) * ratio;
return (0, engine_1.clamp)(value, modeValue, particleValue);
}
}
const Utils_1 = require("./Utils");
class Bubbler extends engine_1.ExternalInteractorBase {
constructor(container) {
super(container);
this._clickBubble = () => {
const container = this.container, options = container.actualOptions, mouseClickPos = container.interactivity.mouse.clickPosition, bubbleOptions = options.interactivity.modes.bubble;
if (!bubbleOptions || !mouseClickPos) {
return;
}
if (!container.bubble) {
container.bubble = {};
}
const distance = container.retina.bubbleModeDistance;
if (!distance || distance < 0) {
return;
}
const query = container.particles.quadTree.queryCircle(mouseClickPos, distance, (p) => this.isEnabled(p)), { bubble } = container;
for (const particle of query) {
if (!bubble.clicking) {
continue;
}
particle.bubble.inRange = !bubble.durationEnd;
const pos = particle.getPosition(), distMouse = (0, engine_1.getDistance)(pos, mouseClickPos), timeSpent = (new Date().getTime() - (container.interactivity.mouse.clickTime || 0)) / 1000;
if (timeSpent > bubbleOptions.duration) {
bubble.durationEnd = true;
}
if (timeSpent > bubbleOptions.duration * 2) {
bubble.clicking = false;
bubble.durationEnd = false;
}
const sizeData = {
bubbleObj: {
optValue: container.retina.bubbleModeSize,
value: particle.bubble.radius,
},
particlesObj: {
optValue: (0, engine_1.getRangeMax)(particle.options.size.value) * container.retina.pixelRatio,
value: particle.size.value,
},
type: "size",
};
this._process(particle, distMouse, timeSpent, sizeData);
const opacityData = {
bubbleObj: {
optValue: bubbleOptions.opacity,
value: particle.bubble.opacity,
},
particlesObj: {
optValue: (0, engine_1.getRangeMax)(particle.options.opacity.value),
value: particle.opacity?.value ?? 1,
},
type: "opacity",
};
this._process(particle, distMouse, timeSpent, opacityData);
if (!bubble.durationEnd && distMouse <= distance) {
this._hoverBubbleColor(particle, distMouse);
}
else {
delete particle.bubble.color;
}
}
};
this._hoverBubble = () => {
const container = this.container, mousePos = container.interactivity.mouse.position, distance = container.retina.bubbleModeDistance;
if (!distance || distance < 0 || mousePos === undefined) {
return;
}
const query = container.particles.quadTree.queryCircle(mousePos, distance, (p) => this.isEnabled(p));
for (const particle of query) {
particle.bubble.inRange = true;
const pos = particle.getPosition(), pointDistance = (0, engine_1.getDistance)(pos, mousePos), ratio = 1 - pointDistance / distance;
if (pointDistance <= distance) {
if (ratio >= 0 && container.interactivity.status === engine_1.mouseMoveEvent) {
this._hoverBubbleSize(particle, ratio);
this._hoverBubbleOpacity(particle, ratio);
this._hoverBubbleColor(particle, ratio);
}
}
else {
this.reset(particle);
}
if (container.interactivity.status === engine_1.mouseLeaveEvent) {
this.reset(particle);
}
}
};
this._hoverBubbleColor = (particle, ratio, divBubble) => {
const options = this.container.actualOptions, bubbleOptions = divBubble ?? options.interactivity.modes.bubble;
if (!bubbleOptions) {
return;
}
if (!particle.bubble.finalColor) {
const modeColor = bubbleOptions.color;
if (!modeColor) {
return;
}
const bubbleColor = (0, engine_1.itemFromSingleOrMultiple)(modeColor);
particle.bubble.finalColor = (0, engine_1.rangeColorToHsl)(bubbleColor);
}
if (!particle.bubble.finalColor) {
return;
}
if (bubbleOptions.mix) {
particle.bubble.color = undefined;
const pColor = particle.getFillColor();
particle.bubble.color = pColor
? (0, engine_1.rgbToHsl)((0, engine_1.colorMix)(pColor, particle.bubble.finalColor, 1 - ratio, ratio))
: particle.bubble.finalColor;
}
else {
particle.bubble.color = particle.bubble.finalColor;
}
};
this._hoverBubbleOpacity = (particle, ratio, divBubble) => {
const container = this.container, options = container.actualOptions, modeOpacity = divBubble?.opacity ?? options.interactivity.modes.bubble?.opacity;
if (!modeOpacity) {
return;
}
const optOpacity = particle.options.opacity.value, pOpacity = particle.opacity?.value ?? 1, opacity = (0, Utils_1.calculateBubbleValue)(pOpacity, modeOpacity, (0, engine_1.getRangeMax)(optOpacity), ratio);
if (opacity !== undefined) {
particle.bubble.opacity = opacity;
}
};
this._hoverBubbleSize = (particle, ratio, divBubble) => {
const container = this.container, modeSize = divBubble?.size ? divBubble.size * container.retina.pixelRatio : container.retina.bubbleModeSize;
if (modeSize === undefined) {
return;
}
const optSize = (0, engine_1.getRangeMax)(particle.options.size.value) * container.retina.pixelRatio, pSize = particle.size.value, size = (0, Utils_1.calculateBubbleValue)(pSize, modeSize, optSize, ratio);
if (size !== undefined) {
particle.bubble.radius = size;
}
};
this._process = (particle, distMouse, timeSpent, data) => {
const container = this.container, bubbleParam = data.bubbleObj.optValue, options = container.actualOptions, bubbleOptions = options.interactivity.modes.bubble;
if (!bubbleOptions || bubbleParam === undefined) {
return;
}
const bubbleDuration = bubbleOptions.duration, bubbleDistance = container.retina.bubbleModeDistance, particlesParam = data.particlesObj.optValue, pObjBubble = data.bubbleObj.value, pObj = data.particlesObj.value || 0, type = data.type;
if (!bubbleDistance || bubbleDistance < 0 || bubbleParam === particlesParam) {
return;
}
if (!container.bubble) {
container.bubble = {};
}
if (container.bubble.durationEnd) {
if (pObjBubble) {
if (type === "size") {
delete particle.bubble.radius;
}
if (type === "opacity") {
delete particle.bubble.opacity;
}
}
}
else {
if (distMouse <= bubbleDistance) {
const obj = pObjBubble ?? pObj;
if (obj !== bubbleParam) {
const value = pObj - (timeSpent * (pObj - bubbleParam)) / bubbleDuration;
if (type === "size") {
particle.bubble.radius = value;
}
if (type === "opacity") {
particle.bubble.opacity = value;
}
}
}
else {
if (type === "size") {
delete particle.bubble.radius;
}
if (type === "opacity") {
delete particle.bubble.opacity;
}
}
}
};
this._singleSelectorHover = (delta, selector, div) => {
const container = this.container, selectors = document.querySelectorAll(selector), bubble = container.actualOptions.interactivity.modes.bubble;
if (!bubble || !selectors.length) {
return;
}
selectors.forEach((item) => {
const elem = item, pxRatio = container.retina.pixelRatio, pos = {
x: (elem.offsetLeft + elem.offsetWidth / 2) * pxRatio,
y: (elem.offsetTop + elem.offsetHeight / 2) * pxRatio,
}, repulseRadius = (elem.offsetWidth / 2) * pxRatio, area = div.type === "circle"
? new engine_1.Circle(pos.x, pos.y, repulseRadius)
: new engine_1.Rectangle(elem.offsetLeft * pxRatio, elem.offsetTop * pxRatio, elem.offsetWidth * pxRatio, elem.offsetHeight * pxRatio), query = container.particles.quadTree.query(area, (p) => this.isEnabled(p));
for (const particle of query) {
if (!area.contains(particle.getPosition())) {
continue;
}
particle.bubble.inRange = true;
const divs = bubble.divs, divBubble = (0, engine_1.divMode)(divs, elem);
if (!particle.bubble.div || particle.bubble.div !== elem) {
this.clear(particle, delta, true);
particle.bubble.div = elem;
}
this._hoverBubbleSize(particle, 1, divBubble);
this._hoverBubbleOpacity(particle, 1, divBubble);
this._hoverBubbleColor(particle, 1, divBubble);
}
});
};
if (!container.bubble) {

@@ -61,25 +245,20 @@ container.bubble = {};

}
interact(delta) {
return __awaiter(this, void 0, void 0, function* () {
const options = this.container.actualOptions, events = options.interactivity.events, onHover = events.onHover, onClick = events.onClick, hoverEnabled = onHover.enable, hoverMode = onHover.mode, clickEnabled = onClick.enable, clickMode = onClick.mode, divs = events.onDiv;
if (hoverEnabled && (0, engine_1.isInArray)("bubble", hoverMode)) {
this.hoverBubble(delta);
}
else if (clickEnabled && (0, engine_1.isInArray)("bubble", clickMode)) {
this.clickBubble(delta);
}
else {
(0, engine_1.divModeExecute)("bubble", divs, (selector, div) => this.singleSelectorHover(delta, selector, div));
}
});
async interact(delta) {
const options = this.container.actualOptions, events = options.interactivity.events, onHover = events.onHover, onClick = events.onClick, hoverEnabled = onHover.enable, hoverMode = onHover.mode, clickEnabled = onClick.enable, clickMode = onClick.mode, divs = events.onDiv;
if (hoverEnabled && (0, engine_1.isInArray)("bubble", hoverMode)) {
this._hoverBubble();
}
else if (clickEnabled && (0, engine_1.isInArray)("bubble", clickMode)) {
this._clickBubble();
}
else {
(0, engine_1.divModeExecute)("bubble", divs, (selector, div) => this._singleSelectorHover(delta, selector, div));
}
}
isEnabled(particle) {
var _a;
const container = this.container, options = container.actualOptions, mouse = container.interactivity.mouse, events = ((_a = particle === null || particle === void 0 ? void 0 : particle.interactivity) !== null && _a !== void 0 ? _a : options.interactivity).events, divs = events.onDiv, divBubble = (0, engine_1.isDivModeEnabled)("bubble", divs);
if (!(divBubble || (events.onHover.enable && mouse.position) || (events.onClick.enable && mouse.clickPosition))) {
const container = this.container, options = container.actualOptions, mouse = container.interactivity.mouse, events = (particle?.interactivity ?? options.interactivity).events, { onClick, onDiv, onHover } = events, divBubble = (0, engine_1.isDivModeEnabled)("bubble", onDiv);
if (!(divBubble || (onHover.enable && mouse.position) || (onClick.enable && mouse.clickPosition))) {
return false;
}
const hoverMode = events.onHover.mode;
const clickMode = events.onClick.mode;
return (0, engine_1.isInArray)("bubble", hoverMode) || (0, engine_1.isInArray)("bubble", clickMode) || divBubble;
return (0, engine_1.isInArray)("bubble", onHover.mode) || (0, engine_1.isInArray)("bubble", onClick.mode) || divBubble;
}

@@ -91,3 +270,3 @@ loadModeOptions(options, ...sources) {

for (const source of sources) {
options.bubble.load(source === null || source === void 0 ? void 0 : source.bubble);
options.bubble.load(source?.bubble);
}

@@ -98,216 +277,3 @@ }

}
clickBubble(delta) {
var _a, _b;
const container = this.container, options = container.actualOptions, mouseClickPos = container.interactivity.mouse.clickPosition, bubble = options.interactivity.modes.bubble;
if (!bubble || !mouseClickPos) {
return;
}
if (!container.bubble) {
container.bubble = {};
}
const distance = container.retina.bubbleModeDistance;
if (!distance || distance < 0) {
return;
}
const query = container.particles.quadTree.queryCircle(mouseClickPos, distance, (p) => this.isEnabled(p));
for (const particle of query) {
if (!container.bubble.clicking) {
continue;
}
particle.bubble.inRange = !container.bubble.durationEnd;
const pos = particle.getPosition(), distMouse = (0, engine_1.getDistance)(pos, mouseClickPos), timeSpent = (new Date().getTime() - (container.interactivity.mouse.clickTime || 0)) / 1000;
if (timeSpent > bubble.duration) {
container.bubble.durationEnd = true;
}
if (timeSpent > bubble.duration * 2) {
container.bubble.clicking = false;
container.bubble.durationEnd = false;
}
const sizeData = {
bubbleObj: {
optValue: container.retina.bubbleModeSize,
value: particle.bubble.radius,
},
particlesObj: {
optValue: (0, engine_1.getRangeMax)(particle.options.size.value) * container.retina.pixelRatio,
value: particle.size.value,
},
type: "size",
};
this.process(particle, distMouse, timeSpent, sizeData);
const opacityData = {
bubbleObj: {
optValue: bubble.opacity,
value: particle.bubble.opacity,
},
particlesObj: {
optValue: (0, engine_1.getRangeMax)(particle.options.opacity.value),
value: (_b = (_a = particle.opacity) === null || _a === void 0 ? void 0 : _a.value) !== null && _b !== void 0 ? _b : 1,
},
type: "opacity",
};
this.process(particle, distMouse, timeSpent, opacityData);
if (!container.bubble.durationEnd) {
if (distMouse <= distance) {
this.hoverBubbleColor(particle, distMouse);
}
else {
delete particle.bubble.color;
}
}
else {
delete particle.bubble.color;
}
}
}
hoverBubble(delta) {
const container = this.container, mousePos = container.interactivity.mouse.position, distance = container.retina.bubbleModeDistance;
if (!distance || distance < 0 || mousePos === undefined) {
return;
}
const query = container.particles.quadTree.queryCircle(mousePos, distance, (p) => this.isEnabled(p));
for (const particle of query) {
particle.bubble.inRange = true;
const pos = particle.getPosition(), pointDistance = (0, engine_1.getDistance)(pos, mousePos), ratio = 1 - pointDistance / distance;
if (pointDistance <= distance) {
if (ratio >= 0 && container.interactivity.status === engine_1.mouseMoveEvent) {
this.hoverBubbleSize(particle, ratio);
this.hoverBubbleOpacity(particle, ratio);
this.hoverBubbleColor(particle, ratio);
}
}
else {
this.reset(particle);
}
if (container.interactivity.status === engine_1.mouseLeaveEvent) {
this.reset(particle);
}
}
}
hoverBubbleColor(particle, ratio, divBubble) {
const options = this.container.actualOptions;
const bubbleOptions = divBubble !== null && divBubble !== void 0 ? divBubble : options.interactivity.modes.bubble;
if (!bubbleOptions) {
return;
}
if (!particle.bubble.finalColor) {
const modeColor = bubbleOptions.color;
if (!modeColor) {
return;
}
const bubbleColor = (0, engine_1.itemFromSingleOrMultiple)(modeColor);
particle.bubble.finalColor = (0, engine_1.rangeColorToHsl)(bubbleColor);
}
if (!particle.bubble.finalColor) {
return;
}
if (bubbleOptions.mix) {
particle.bubble.color = undefined;
const pColor = particle.getFillColor();
particle.bubble.color = pColor
? (0, engine_1.rgbToHsl)((0, engine_1.colorMix)(pColor, particle.bubble.finalColor, 1 - ratio, ratio))
: particle.bubble.finalColor;
}
else {
particle.bubble.color = particle.bubble.finalColor;
}
}
hoverBubbleOpacity(particle, ratio, divBubble) {
var _a, _b, _c, _d;
const container = this.container, options = container.actualOptions, modeOpacity = (_a = divBubble === null || divBubble === void 0 ? void 0 : divBubble.opacity) !== null && _a !== void 0 ? _a : (_b = options.interactivity.modes.bubble) === null || _b === void 0 ? void 0 : _b.opacity;
if (!modeOpacity) {
return;
}
const optOpacity = particle.options.opacity.value;
const pOpacity = (_d = (_c = particle.opacity) === null || _c === void 0 ? void 0 : _c.value) !== null && _d !== void 0 ? _d : 1;
const opacity = calculateBubbleValue(pOpacity, modeOpacity, (0, engine_1.getRangeMax)(optOpacity), ratio);
if (opacity !== undefined) {
particle.bubble.opacity = opacity;
}
}
hoverBubbleSize(particle, ratio, divBubble) {
const container = this.container, modeSize = (divBubble === null || divBubble === void 0 ? void 0 : divBubble.size) ? divBubble.size * container.retina.pixelRatio : container.retina.bubbleModeSize;
if (modeSize === undefined) {
return;
}
const optSize = (0, engine_1.getRangeMax)(particle.options.size.value) * container.retina.pixelRatio;
const pSize = particle.size.value;
const size = calculateBubbleValue(pSize, modeSize, optSize, ratio);
if (size !== undefined) {
particle.bubble.radius = size;
}
}
process(particle, distMouse, timeSpent, data) {
const container = this.container, bubbleParam = data.bubbleObj.optValue, options = container.actualOptions, bubble = options.interactivity.modes.bubble;
if (!bubble || bubbleParam === undefined) {
return;
}
const bubbleDuration = bubble.duration, bubbleDistance = container.retina.bubbleModeDistance, particlesParam = data.particlesObj.optValue, pObjBubble = data.bubbleObj.value, pObj = data.particlesObj.value || 0, type = data.type;
if (!bubbleDistance || bubbleDistance < 0 || bubbleParam === particlesParam) {
return;
}
if (!container.bubble) {
container.bubble = {};
}
if (!container.bubble.durationEnd) {
if (distMouse <= bubbleDistance) {
const obj = pObjBubble !== null && pObjBubble !== void 0 ? pObjBubble : pObj;
if (obj !== bubbleParam) {
const value = pObj - (timeSpent * (pObj - bubbleParam)) / bubbleDuration;
if (type === "size") {
particle.bubble.radius = value;
}
if (type === "opacity") {
particle.bubble.opacity = value;
}
}
}
else {
if (type === "size") {
delete particle.bubble.radius;
}
if (type === "opacity") {
delete particle.bubble.opacity;
}
}
}
else if (pObjBubble) {
if (type === "size") {
delete particle.bubble.radius;
}
if (type === "opacity") {
delete particle.bubble.opacity;
}
}
}
singleSelectorHover(delta, selector, div) {
const container = this.container, selectors = document.querySelectorAll(selector), bubble = container.actualOptions.interactivity.modes.bubble;
if (!bubble || !selectors.length) {
return;
}
selectors.forEach((item) => {
const elem = item, pxRatio = container.retina.pixelRatio, pos = {
x: (elem.offsetLeft + elem.offsetWidth / 2) * pxRatio,
y: (elem.offsetTop + elem.offsetHeight / 2) * pxRatio,
}, repulseRadius = (elem.offsetWidth / 2) * pxRatio, area = div.type === "circle"
? new engine_1.Circle(pos.x, pos.y, repulseRadius)
: new engine_1.Rectangle(elem.offsetLeft * pxRatio, elem.offsetTop * pxRatio, elem.offsetWidth * pxRatio, elem.offsetHeight * pxRatio), query = container.particles.quadTree.query(area, (p) => this.isEnabled(p));
for (const particle of query) {
if (!area.contains(particle.getPosition())) {
continue;
}
particle.bubble.inRange = true;
const divs = bubble.divs;
const divBubble = (0, engine_1.divMode)(divs, elem);
if (!particle.bubble.div || particle.bubble.div !== elem) {
this.clear(particle, delta, true);
particle.bubble.div = elem;
}
this.hoverBubbleSize(particle, 1, divBubble);
this.hoverBubbleOpacity(particle, 1, divBubble);
this.hoverBubbleColor(particle, 1, divBubble);
}
});
}
}
exports.Bubbler = Bubbler;

@@ -16,18 +16,7 @@ "use strict";

};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.loadExternalBubbleInteraction = void 0;
const Bubbler_1 = require("./Bubbler");
function loadExternalBubbleInteraction(engine) {
return __awaiter(this, void 0, void 0, function* () {
yield engine.addInteractor("externalBubble", (container) => new Bubbler_1.Bubbler(container));
});
async function loadExternalBubbleInteraction(engine, refresh = true) {
await engine.addInteractor("externalBubble", (container) => new Bubbler_1.Bubbler(container), refresh);
}

@@ -34,0 +23,0 @@ exports.loadExternalBubbleInteraction = loadExternalBubbleInteraction;

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Bubble = void 0;
const engine_1 = require("@tsparticles/engine");
const BubbleBase_1 = require("./BubbleBase");
const BubbleDiv_1 = require("./BubbleDiv");
const engine_1 = require("@tsparticles/engine");
class Bubble extends BubbleBase_1.BubbleBase {

@@ -8,0 +8,0 @@ load(data) {

@@ -28,3 +28,3 @@ "use strict";

if (data.color !== undefined) {
const sourceColor = this.color instanceof Array ? undefined : this.color;
const sourceColor = (0, engine_1.isArray)(this.color) ? undefined : this.color;
this.color = (0, engine_1.executeOnSingleOrMultiple)(data.color, (color) => {

@@ -31,0 +31,0 @@ return engine_1.OptionsColor.create(sourceColor, color);

@@ -5,3 +5,2 @@ "use strict";

const BubbleBase_1 = require("./BubbleBase");
const engine_1 = require("@tsparticles/engine");
class BubbleDiv extends BubbleBase_1.BubbleBase {

@@ -12,8 +11,2 @@ constructor() {

}
get ids() {
return (0, engine_1.executeOnSingleOrMultiple)(this.selectors, (t) => t.replace("#", ""));
}
set ids(value) {
this.selectors = (0, engine_1.executeOnSingleOrMultiple)(value, (t) => `#${t}`);
}
load(data) {

@@ -24,5 +17,2 @@ super.load(data);

}
if (data.ids !== undefined) {
this.ids = data.ids;
}
if (data.selectors !== undefined) {

@@ -29,0 +19,0 @@ this.selectors = data.selectors;

@@ -1,16 +0,209 @@

import { Circle, ExternalInteractorBase, Rectangle, clamp, colorMix, divMode, divModeExecute, getDistance, getRangeMax, isDivModeEnabled, isInArray, itemFromSingleOrMultiple, mouseLeaveEvent, mouseMoveEvent, rangeColorToHsl, rgbToHsl, } from "@tsparticles/engine";
import { Circle, ExternalInteractorBase, Rectangle, colorMix, divMode, divModeExecute, getDistance, getRangeMax, isDivModeEnabled, isInArray, itemFromSingleOrMultiple, mouseLeaveEvent, mouseMoveEvent, rangeColorToHsl, rgbToHsl, } from "@tsparticles/engine";
import { Bubble } from "./Options/Classes/Bubble";
function calculateBubbleValue(particleValue, modeValue, optionsValue, ratio) {
if (modeValue >= optionsValue) {
const value = particleValue + (modeValue - optionsValue) * ratio;
return clamp(value, particleValue, modeValue);
}
else if (modeValue < optionsValue) {
const value = particleValue - (optionsValue - modeValue) * ratio;
return clamp(value, modeValue, particleValue);
}
}
import { calculateBubbleValue } from "./Utils";
export class Bubbler extends ExternalInteractorBase {
constructor(container) {
super(container);
this._clickBubble = () => {
const container = this.container, options = container.actualOptions, mouseClickPos = container.interactivity.mouse.clickPosition, bubbleOptions = options.interactivity.modes.bubble;
if (!bubbleOptions || !mouseClickPos) {
return;
}
if (!container.bubble) {
container.bubble = {};
}
const distance = container.retina.bubbleModeDistance;
if (!distance || distance < 0) {
return;
}
const query = container.particles.quadTree.queryCircle(mouseClickPos, distance, (p) => this.isEnabled(p)), { bubble } = container;
for (const particle of query) {
if (!bubble.clicking) {
continue;
}
particle.bubble.inRange = !bubble.durationEnd;
const pos = particle.getPosition(), distMouse = getDistance(pos, mouseClickPos), timeSpent = (new Date().getTime() - (container.interactivity.mouse.clickTime || 0)) / 1000;
if (timeSpent > bubbleOptions.duration) {
bubble.durationEnd = true;
}
if (timeSpent > bubbleOptions.duration * 2) {
bubble.clicking = false;
bubble.durationEnd = false;
}
const sizeData = {
bubbleObj: {
optValue: container.retina.bubbleModeSize,
value: particle.bubble.radius,
},
particlesObj: {
optValue: getRangeMax(particle.options.size.value) * container.retina.pixelRatio,
value: particle.size.value,
},
type: "size",
};
this._process(particle, distMouse, timeSpent, sizeData);
const opacityData = {
bubbleObj: {
optValue: bubbleOptions.opacity,
value: particle.bubble.opacity,
},
particlesObj: {
optValue: getRangeMax(particle.options.opacity.value),
value: particle.opacity?.value ?? 1,
},
type: "opacity",
};
this._process(particle, distMouse, timeSpent, opacityData);
if (!bubble.durationEnd && distMouse <= distance) {
this._hoverBubbleColor(particle, distMouse);
}
else {
delete particle.bubble.color;
}
}
};
this._hoverBubble = () => {
const container = this.container, mousePos = container.interactivity.mouse.position, distance = container.retina.bubbleModeDistance;
if (!distance || distance < 0 || mousePos === undefined) {
return;
}
const query = container.particles.quadTree.queryCircle(mousePos, distance, (p) => this.isEnabled(p));
for (const particle of query) {
particle.bubble.inRange = true;
const pos = particle.getPosition(), pointDistance = getDistance(pos, mousePos), ratio = 1 - pointDistance / distance;
if (pointDistance <= distance) {
if (ratio >= 0 && container.interactivity.status === mouseMoveEvent) {
this._hoverBubbleSize(particle, ratio);
this._hoverBubbleOpacity(particle, ratio);
this._hoverBubbleColor(particle, ratio);
}
}
else {
this.reset(particle);
}
if (container.interactivity.status === mouseLeaveEvent) {
this.reset(particle);
}
}
};
this._hoverBubbleColor = (particle, ratio, divBubble) => {
const options = this.container.actualOptions, bubbleOptions = divBubble ?? options.interactivity.modes.bubble;
if (!bubbleOptions) {
return;
}
if (!particle.bubble.finalColor) {
const modeColor = bubbleOptions.color;
if (!modeColor) {
return;
}
const bubbleColor = itemFromSingleOrMultiple(modeColor);
particle.bubble.finalColor = rangeColorToHsl(bubbleColor);
}
if (!particle.bubble.finalColor) {
return;
}
if (bubbleOptions.mix) {
particle.bubble.color = undefined;
const pColor = particle.getFillColor();
particle.bubble.color = pColor
? rgbToHsl(colorMix(pColor, particle.bubble.finalColor, 1 - ratio, ratio))
: particle.bubble.finalColor;
}
else {
particle.bubble.color = particle.bubble.finalColor;
}
};
this._hoverBubbleOpacity = (particle, ratio, divBubble) => {
const container = this.container, options = container.actualOptions, modeOpacity = divBubble?.opacity ?? options.interactivity.modes.bubble?.opacity;
if (!modeOpacity) {
return;
}
const optOpacity = particle.options.opacity.value, pOpacity = particle.opacity?.value ?? 1, opacity = calculateBubbleValue(pOpacity, modeOpacity, getRangeMax(optOpacity), ratio);
if (opacity !== undefined) {
particle.bubble.opacity = opacity;
}
};
this._hoverBubbleSize = (particle, ratio, divBubble) => {
const container = this.container, modeSize = divBubble?.size ? divBubble.size * container.retina.pixelRatio : container.retina.bubbleModeSize;
if (modeSize === undefined) {
return;
}
const optSize = getRangeMax(particle.options.size.value) * container.retina.pixelRatio, pSize = particle.size.value, size = calculateBubbleValue(pSize, modeSize, optSize, ratio);
if (size !== undefined) {
particle.bubble.radius = size;
}
};
this._process = (particle, distMouse, timeSpent, data) => {
const container = this.container, bubbleParam = data.bubbleObj.optValue, options = container.actualOptions, bubbleOptions = options.interactivity.modes.bubble;
if (!bubbleOptions || bubbleParam === undefined) {
return;
}
const bubbleDuration = bubbleOptions.duration, bubbleDistance = container.retina.bubbleModeDistance, particlesParam = data.particlesObj.optValue, pObjBubble = data.bubbleObj.value, pObj = data.particlesObj.value || 0, type = data.type;
if (!bubbleDistance || bubbleDistance < 0 || bubbleParam === particlesParam) {
return;
}
if (!container.bubble) {
container.bubble = {};
}
if (container.bubble.durationEnd) {
if (pObjBubble) {
if (type === "size") {
delete particle.bubble.radius;
}
if (type === "opacity") {
delete particle.bubble.opacity;
}
}
}
else {
if (distMouse <= bubbleDistance) {
const obj = pObjBubble ?? pObj;
if (obj !== bubbleParam) {
const value = pObj - (timeSpent * (pObj - bubbleParam)) / bubbleDuration;
if (type === "size") {
particle.bubble.radius = value;
}
if (type === "opacity") {
particle.bubble.opacity = value;
}
}
}
else {
if (type === "size") {
delete particle.bubble.radius;
}
if (type === "opacity") {
delete particle.bubble.opacity;
}
}
}
};
this._singleSelectorHover = (delta, selector, div) => {
const container = this.container, selectors = document.querySelectorAll(selector), bubble = container.actualOptions.interactivity.modes.bubble;
if (!bubble || !selectors.length) {
return;
}
selectors.forEach((item) => {
const elem = item, pxRatio = container.retina.pixelRatio, pos = {
x: (elem.offsetLeft + elem.offsetWidth / 2) * pxRatio,
y: (elem.offsetTop + elem.offsetHeight / 2) * pxRatio,
}, repulseRadius = (elem.offsetWidth / 2) * pxRatio, area = div.type === "circle"
? new Circle(pos.x, pos.y, repulseRadius)
: new Rectangle(elem.offsetLeft * pxRatio, elem.offsetTop * pxRatio, elem.offsetWidth * pxRatio, elem.offsetHeight * pxRatio), query = container.particles.quadTree.query(area, (p) => this.isEnabled(p));
for (const particle of query) {
if (!area.contains(particle.getPosition())) {
continue;
}
particle.bubble.inRange = true;
const divs = bubble.divs, divBubble = divMode(divs, elem);
if (!particle.bubble.div || particle.bubble.div !== elem) {
this.clear(particle, delta, true);
particle.bubble.div = elem;
}
this._hoverBubbleSize(particle, 1, divBubble);
this._hoverBubbleOpacity(particle, 1, divBubble);
this._hoverBubbleColor(particle, 1, divBubble);
}
});
};
if (!container.bubble) {

@@ -51,20 +244,17 @@ container.bubble = {};

if (hoverEnabled && isInArray("bubble", hoverMode)) {
this.hoverBubble(delta);
this._hoverBubble();
}
else if (clickEnabled && isInArray("bubble", clickMode)) {
this.clickBubble(delta);
this._clickBubble();
}
else {
divModeExecute("bubble", divs, (selector, div) => this.singleSelectorHover(delta, selector, div));
divModeExecute("bubble", divs, (selector, div) => this._singleSelectorHover(delta, selector, div));
}
}
isEnabled(particle) {
var _a;
const container = this.container, options = container.actualOptions, mouse = container.interactivity.mouse, events = ((_a = particle === null || particle === void 0 ? void 0 : particle.interactivity) !== null && _a !== void 0 ? _a : options.interactivity).events, divs = events.onDiv, divBubble = isDivModeEnabled("bubble", divs);
if (!(divBubble || (events.onHover.enable && mouse.position) || (events.onClick.enable && mouse.clickPosition))) {
const container = this.container, options = container.actualOptions, mouse = container.interactivity.mouse, events = (particle?.interactivity ?? options.interactivity).events, { onClick, onDiv, onHover } = events, divBubble = isDivModeEnabled("bubble", onDiv);
if (!(divBubble || (onHover.enable && mouse.position) || (onClick.enable && mouse.clickPosition))) {
return false;
}
const hoverMode = events.onHover.mode;
const clickMode = events.onClick.mode;
return isInArray("bubble", hoverMode) || isInArray("bubble", clickMode) || divBubble;
return isInArray("bubble", onHover.mode) || isInArray("bubble", onClick.mode) || divBubble;
}

@@ -76,3 +266,3 @@ loadModeOptions(options, ...sources) {

for (const source of sources) {
options.bubble.load(source === null || source === void 0 ? void 0 : source.bubble);
options.bubble.load(source?.bubble);
}

@@ -83,215 +273,2 @@ }

}
clickBubble(delta) {
var _a, _b;
const container = this.container, options = container.actualOptions, mouseClickPos = container.interactivity.mouse.clickPosition, bubble = options.interactivity.modes.bubble;
if (!bubble || !mouseClickPos) {
return;
}
if (!container.bubble) {
container.bubble = {};
}
const distance = container.retina.bubbleModeDistance;
if (!distance || distance < 0) {
return;
}
const query = container.particles.quadTree.queryCircle(mouseClickPos, distance, (p) => this.isEnabled(p));
for (const particle of query) {
if (!container.bubble.clicking) {
continue;
}
particle.bubble.inRange = !container.bubble.durationEnd;
const pos = particle.getPosition(), distMouse = getDistance(pos, mouseClickPos), timeSpent = (new Date().getTime() - (container.interactivity.mouse.clickTime || 0)) / 1000;
if (timeSpent > bubble.duration) {
container.bubble.durationEnd = true;
}
if (timeSpent > bubble.duration * 2) {
container.bubble.clicking = false;
container.bubble.durationEnd = false;
}
const sizeData = {
bubbleObj: {
optValue: container.retina.bubbleModeSize,
value: particle.bubble.radius,
},
particlesObj: {
optValue: getRangeMax(particle.options.size.value) * container.retina.pixelRatio,
value: particle.size.value,
},
type: "size",
};
this.process(particle, distMouse, timeSpent, sizeData);
const opacityData = {
bubbleObj: {
optValue: bubble.opacity,
value: particle.bubble.opacity,
},
particlesObj: {
optValue: getRangeMax(particle.options.opacity.value),
value: (_b = (_a = particle.opacity) === null || _a === void 0 ? void 0 : _a.value) !== null && _b !== void 0 ? _b : 1,
},
type: "opacity",
};
this.process(particle, distMouse, timeSpent, opacityData);
if (!container.bubble.durationEnd) {
if (distMouse <= distance) {
this.hoverBubbleColor(particle, distMouse);
}
else {
delete particle.bubble.color;
}
}
else {
delete particle.bubble.color;
}
}
}
hoverBubble(delta) {
const container = this.container, mousePos = container.interactivity.mouse.position, distance = container.retina.bubbleModeDistance;
if (!distance || distance < 0 || mousePos === undefined) {
return;
}
const query = container.particles.quadTree.queryCircle(mousePos, distance, (p) => this.isEnabled(p));
for (const particle of query) {
particle.bubble.inRange = true;
const pos = particle.getPosition(), pointDistance = getDistance(pos, mousePos), ratio = 1 - pointDistance / distance;
if (pointDistance <= distance) {
if (ratio >= 0 && container.interactivity.status === mouseMoveEvent) {
this.hoverBubbleSize(particle, ratio);
this.hoverBubbleOpacity(particle, ratio);
this.hoverBubbleColor(particle, ratio);
}
}
else {
this.reset(particle);
}
if (container.interactivity.status === mouseLeaveEvent) {
this.reset(particle);
}
}
}
hoverBubbleColor(particle, ratio, divBubble) {
const options = this.container.actualOptions;
const bubbleOptions = divBubble !== null && divBubble !== void 0 ? divBubble : options.interactivity.modes.bubble;
if (!bubbleOptions) {
return;
}
if (!particle.bubble.finalColor) {
const modeColor = bubbleOptions.color;
if (!modeColor) {
return;
}
const bubbleColor = itemFromSingleOrMultiple(modeColor);
particle.bubble.finalColor = rangeColorToHsl(bubbleColor);
}
if (!particle.bubble.finalColor) {
return;
}
if (bubbleOptions.mix) {
particle.bubble.color = undefined;
const pColor = particle.getFillColor();
particle.bubble.color = pColor
? rgbToHsl(colorMix(pColor, particle.bubble.finalColor, 1 - ratio, ratio))
: particle.bubble.finalColor;
}
else {
particle.bubble.color = particle.bubble.finalColor;
}
}
hoverBubbleOpacity(particle, ratio, divBubble) {
var _a, _b, _c, _d;
const container = this.container, options = container.actualOptions, modeOpacity = (_a = divBubble === null || divBubble === void 0 ? void 0 : divBubble.opacity) !== null && _a !== void 0 ? _a : (_b = options.interactivity.modes.bubble) === null || _b === void 0 ? void 0 : _b.opacity;
if (!modeOpacity) {
return;
}
const optOpacity = particle.options.opacity.value;
const pOpacity = (_d = (_c = particle.opacity) === null || _c === void 0 ? void 0 : _c.value) !== null && _d !== void 0 ? _d : 1;
const opacity = calculateBubbleValue(pOpacity, modeOpacity, getRangeMax(optOpacity), ratio);
if (opacity !== undefined) {
particle.bubble.opacity = opacity;
}
}
hoverBubbleSize(particle, ratio, divBubble) {
const container = this.container, modeSize = (divBubble === null || divBubble === void 0 ? void 0 : divBubble.size) ? divBubble.size * container.retina.pixelRatio : container.retina.bubbleModeSize;
if (modeSize === undefined) {
return;
}
const optSize = getRangeMax(particle.options.size.value) * container.retina.pixelRatio;
const pSize = particle.size.value;
const size = calculateBubbleValue(pSize, modeSize, optSize, ratio);
if (size !== undefined) {
particle.bubble.radius = size;
}
}
process(particle, distMouse, timeSpent, data) {
const container = this.container, bubbleParam = data.bubbleObj.optValue, options = container.actualOptions, bubble = options.interactivity.modes.bubble;
if (!bubble || bubbleParam === undefined) {
return;
}
const bubbleDuration = bubble.duration, bubbleDistance = container.retina.bubbleModeDistance, particlesParam = data.particlesObj.optValue, pObjBubble = data.bubbleObj.value, pObj = data.particlesObj.value || 0, type = data.type;
if (!bubbleDistance || bubbleDistance < 0 || bubbleParam === particlesParam) {
return;
}
if (!container.bubble) {
container.bubble = {};
}
if (!container.bubble.durationEnd) {
if (distMouse <= bubbleDistance) {
const obj = pObjBubble !== null && pObjBubble !== void 0 ? pObjBubble : pObj;
if (obj !== bubbleParam) {
const value = pObj - (timeSpent * (pObj - bubbleParam)) / bubbleDuration;
if (type === "size") {
particle.bubble.radius = value;
}
if (type === "opacity") {
particle.bubble.opacity = value;
}
}
}
else {
if (type === "size") {
delete particle.bubble.radius;
}
if (type === "opacity") {
delete particle.bubble.opacity;
}
}
}
else if (pObjBubble) {
if (type === "size") {
delete particle.bubble.radius;
}
if (type === "opacity") {
delete particle.bubble.opacity;
}
}
}
singleSelectorHover(delta, selector, div) {
const container = this.container, selectors = document.querySelectorAll(selector), bubble = container.actualOptions.interactivity.modes.bubble;
if (!bubble || !selectors.length) {
return;
}
selectors.forEach((item) => {
const elem = item, pxRatio = container.retina.pixelRatio, pos = {
x: (elem.offsetLeft + elem.offsetWidth / 2) * pxRatio,
y: (elem.offsetTop + elem.offsetHeight / 2) * pxRatio,
}, repulseRadius = (elem.offsetWidth / 2) * pxRatio, area = div.type === "circle"
? new Circle(pos.x, pos.y, repulseRadius)
: new Rectangle(elem.offsetLeft * pxRatio, elem.offsetTop * pxRatio, elem.offsetWidth * pxRatio, elem.offsetHeight * pxRatio), query = container.particles.quadTree.query(area, (p) => this.isEnabled(p));
for (const particle of query) {
if (!area.contains(particle.getPosition())) {
continue;
}
particle.bubble.inRange = true;
const divs = bubble.divs;
const divBubble = divMode(divs, elem);
if (!particle.bubble.div || particle.bubble.div !== elem) {
this.clear(particle, delta, true);
particle.bubble.div = elem;
}
this.hoverBubbleSize(particle, 1, divBubble);
this.hoverBubbleOpacity(particle, 1, divBubble);
this.hoverBubbleColor(particle, 1, divBubble);
}
});
}
}
import { Bubbler } from "./Bubbler";
export async function loadExternalBubbleInteraction(engine) {
await engine.addInteractor("externalBubble", (container) => new Bubbler(container));
export async function loadExternalBubbleInteraction(engine, refresh = true) {
await engine.addInteractor("externalBubble", (container) => new Bubbler(container), refresh);
}

@@ -5,0 +5,0 @@ export * from "./Options/Classes/BubbleBase";

@@ -0,4 +1,4 @@

import { executeOnSingleOrMultiple, } from "@tsparticles/engine";
import { BubbleBase } from "./BubbleBase";
import { BubbleDiv } from "./BubbleDiv";
import { executeOnSingleOrMultiple } from "@tsparticles/engine";
export class Bubble extends BubbleBase {

@@ -5,0 +5,0 @@ load(data) {

@@ -1,2 +0,2 @@

import { OptionsColor, executeOnSingleOrMultiple } from "@tsparticles/engine";
import { OptionsColor, executeOnSingleOrMultiple, isArray, } from "@tsparticles/engine";
export class BubbleBase {

@@ -25,3 +25,3 @@ constructor() {

if (data.color !== undefined) {
const sourceColor = this.color instanceof Array ? undefined : this.color;
const sourceColor = isArray(this.color) ? undefined : this.color;
this.color = executeOnSingleOrMultiple(data.color, (color) => {

@@ -28,0 +28,0 @@ return OptionsColor.create(sourceColor, color);

import { BubbleBase } from "./BubbleBase";
import { executeOnSingleOrMultiple } from "@tsparticles/engine";
export class BubbleDiv extends BubbleBase {

@@ -8,8 +7,2 @@ constructor() {

}
get ids() {
return executeOnSingleOrMultiple(this.selectors, (t) => t.replace("#", ""));
}
set ids(value) {
this.selectors = executeOnSingleOrMultiple(value, (t) => `#${t}`);
}
load(data) {

@@ -20,5 +13,2 @@ super.load(data);

}
if (data.ids !== undefined) {
this.ids = data.ids;
}
if (data.selectors !== undefined) {

@@ -25,0 +15,0 @@ this.selectors = data.selectors;

{
"name": "@tsparticles/interaction-external-bubble",
"version": "3.0.0-alpha.1",
"version": "3.0.0-beta.0",
"description": "tsParticles bubble external interaction",

@@ -76,8 +76,9 @@ "homepage": "https://particles.js.org",

"types": "types/index.d.ts",
"sideEffects": false,
"dependencies": {
"@tsparticles/engine": "^3.0.0-beta.0"
},
"publishConfig": {
"access": "public"
},
"dependencies": {
"@tsparticles/engine": "^3.0.0-alpha.1"
}
}
}

@@ -5,5 +5,5 @@ [![banner](https://particles.js.org/images/banner2.png)](https://particles.js.org)

[![jsDelivr](https://data.jsdelivr.com/v1/package/npm/tsparticles-interaction-external-bubble/badge)](https://www.jsdelivr.com/package/npm/tsparticles-interaction-external-bubble)
[![npmjs](https://badge.fury.io/js/tsparticles-interaction-external-bubble.svg)](https://www.npmjs.com/package/tsparticles-interaction-external-bubble)
[![npmjs](https://img.shields.io/npm/dt/tsparticles-interaction-external-bubble)](https://www.npmjs.com/package/tsparticles-interaction-external-bubble) [![GitHub Sponsors](https://img.shields.io/github/sponsors/matteobruni)](https://github.com/sponsors/matteobruni)
[![jsDelivr](https://data.jsdelivr.com/v1/package/npm/@tsparticles/interaction-external-bubble/badge)](https://www.jsdelivr.com/package/npm/@tsparticles/interaction-external-bubble)
[![npmjs](https://badge.fury.io/js/@tsparticles/interaction-external-bubble.svg)](https://www.npmjs.com/package/@tsparticles/interaction-external-bubble)
[![npmjs](https://img.shields.io/npm/dt/@tsparticles/interaction-external-bubble)](https://www.npmjs.com/package/@tsparticles/interaction-external-bubble) [![GitHub Sponsors](https://img.shields.io/github/sponsors/matteobruni)](https://github.com/sponsors/matteobruni)

@@ -31,10 +31,12 @@ [tsParticles](https://github.com/matteobruni/tsparticles) interaction plugin for bubble effect around mouse or HTML

```javascript
loadExternalBubbleInteraction(tsParticles);
(async () => {
await loadExternalBubbleInteraction(tsParticles);
tsParticles.load({
id: "tsparticles",
options: {
/* options */
},
});
await tsParticles.load({
id: "tsparticles",
options: {
/* options */
},
});
})();
```

@@ -47,3 +49,3 @@

```shell
$ npm install tsparticles-interaction-external-bubble
$ npm install @tsparticles/interaction-external-bubble
```

@@ -54,3 +56,3 @@

```shell
$ yarn add tsparticles-interaction-external-bubble
$ yarn add @tsparticles/interaction-external-bubble
```

@@ -61,6 +63,8 @@

```javascript
const { tsParticles } = require("tsparticles-engine");
const { loadExternalBubbleInteraction } = require("tsparticles-interaction-external-bubble");
const { tsParticles } = require("@tsparticles/engine");
const { loadExternalBubbleInteraction } = require("@tsparticles/interaction-external-bubble");
loadExternalBubbleInteraction(tsParticles);
(async () => {
await loadExternalBubbleInteraction(tsParticles);
})();
```

@@ -71,6 +75,8 @@

```javascript
import { tsParticles } from "tsparticles-engine";
import { loadExternalBubbleInteraction } from "tsparticles-interaction-external-bubble";
import { tsParticles } from "@tsparticles/engine";
import { loadExternalBubbleInteraction } from "@tsparticles/interaction-external-bubble";
loadExternalBubbleInteraction(tsParticles);
(async () => {
await loadExternalBubbleInteraction(tsParticles);
})();
```

@@ -7,3 +7,3 @@ /*!

* How to use? : Check the GitHub README
* v3.0.0-alpha.1
* v3.0.0-beta.0
*/

@@ -95,6 +95,6 @@ (function webpackUniversalModuleDefinition(root, factory) {

__webpack_require__.d(__webpack_exports__, {
"Bubble": () => (/* reexport */ Bubble),
"BubbleBase": () => (/* reexport */ BubbleBase),
"BubbleDiv": () => (/* reexport */ BubbleDiv),
"loadExternalBubbleInteraction": () => (/* binding */ loadExternalBubbleInteraction)
Bubble: () => (/* reexport */ Bubble),
BubbleBase: () => (/* reexport */ BubbleBase),
BubbleDiv: () => (/* reexport */ BubbleDiv),
loadExternalBubbleInteraction: () => (/* binding */ loadExternalBubbleInteraction)
});

@@ -129,3 +129,3 @@

if (data.color !== undefined) {
const sourceColor = this.color instanceof Array ? undefined : this.color;
const sourceColor = (0,engine_root_window_.isArray)(this.color) ? undefined : this.color;
this.color = (0,engine_root_window_.executeOnSingleOrMultiple)(data.color, color => {

@@ -142,3 +142,2 @@ return engine_root_window_.OptionsColor.create(sourceColor, color);

class BubbleDiv extends BubbleBase {

@@ -149,8 +148,2 @@ constructor() {

}
get ids() {
return (0,engine_root_window_.executeOnSingleOrMultiple)(this.selectors, t => t.replace("#", ""));
}
set ids(value) {
this.selectors = (0,engine_root_window_.executeOnSingleOrMultiple)(value, t => `#${t}`);
}
load(data) {

@@ -161,5 +154,2 @@ super.load(data);

}
if (data.ids !== undefined) {
this.ids = data.ids;
}
if (data.selectors !== undefined) {

@@ -187,5 +177,4 @@ this.selectors = data.selectors;

}
;// CONCATENATED MODULE: ./dist/browser/Bubbler.js
;// CONCATENATED MODULE: ./dist/browser/Utils.js
function calculateBubbleValue(particleValue, modeValue, optionsValue, ratio) {

@@ -200,5 +189,238 @@ if (modeValue >= optionsValue) {

}
;// CONCATENATED MODULE: ./dist/browser/Bubbler.js
class Bubbler extends engine_root_window_.ExternalInteractorBase {
constructor(container) {
super(container);
this._clickBubble = () => {
const container = this.container,
options = container.actualOptions,
mouseClickPos = container.interactivity.mouse.clickPosition,
bubbleOptions = options.interactivity.modes.bubble;
if (!bubbleOptions || !mouseClickPos) {
return;
}
if (!container.bubble) {
container.bubble = {};
}
const distance = container.retina.bubbleModeDistance;
if (!distance || distance < 0) {
return;
}
const query = container.particles.quadTree.queryCircle(mouseClickPos, distance, p => this.isEnabled(p)),
{
bubble
} = container;
for (const particle of query) {
if (!bubble.clicking) {
continue;
}
particle.bubble.inRange = !bubble.durationEnd;
const pos = particle.getPosition(),
distMouse = (0,engine_root_window_.getDistance)(pos, mouseClickPos),
timeSpent = (new Date().getTime() - (container.interactivity.mouse.clickTime || 0)) / 1000;
if (timeSpent > bubbleOptions.duration) {
bubble.durationEnd = true;
}
if (timeSpent > bubbleOptions.duration * 2) {
bubble.clicking = false;
bubble.durationEnd = false;
}
const sizeData = {
bubbleObj: {
optValue: container.retina.bubbleModeSize,
value: particle.bubble.radius
},
particlesObj: {
optValue: (0,engine_root_window_.getRangeMax)(particle.options.size.value) * container.retina.pixelRatio,
value: particle.size.value
},
type: "size"
};
this._process(particle, distMouse, timeSpent, sizeData);
const opacityData = {
bubbleObj: {
optValue: bubbleOptions.opacity,
value: particle.bubble.opacity
},
particlesObj: {
optValue: (0,engine_root_window_.getRangeMax)(particle.options.opacity.value),
value: particle.opacity?.value ?? 1
},
type: "opacity"
};
this._process(particle, distMouse, timeSpent, opacityData);
if (!bubble.durationEnd && distMouse <= distance) {
this._hoverBubbleColor(particle, distMouse);
} else {
delete particle.bubble.color;
}
}
};
this._hoverBubble = () => {
const container = this.container,
mousePos = container.interactivity.mouse.position,
distance = container.retina.bubbleModeDistance;
if (!distance || distance < 0 || mousePos === undefined) {
return;
}
const query = container.particles.quadTree.queryCircle(mousePos, distance, p => this.isEnabled(p));
for (const particle of query) {
particle.bubble.inRange = true;
const pos = particle.getPosition(),
pointDistance = (0,engine_root_window_.getDistance)(pos, mousePos),
ratio = 1 - pointDistance / distance;
if (pointDistance <= distance) {
if (ratio >= 0 && container.interactivity.status === engine_root_window_.mouseMoveEvent) {
this._hoverBubbleSize(particle, ratio);
this._hoverBubbleOpacity(particle, ratio);
this._hoverBubbleColor(particle, ratio);
}
} else {
this.reset(particle);
}
if (container.interactivity.status === engine_root_window_.mouseLeaveEvent) {
this.reset(particle);
}
}
};
this._hoverBubbleColor = (particle, ratio, divBubble) => {
const options = this.container.actualOptions,
bubbleOptions = divBubble ?? options.interactivity.modes.bubble;
if (!bubbleOptions) {
return;
}
if (!particle.bubble.finalColor) {
const modeColor = bubbleOptions.color;
if (!modeColor) {
return;
}
const bubbleColor = (0,engine_root_window_.itemFromSingleOrMultiple)(modeColor);
particle.bubble.finalColor = (0,engine_root_window_.rangeColorToHsl)(bubbleColor);
}
if (!particle.bubble.finalColor) {
return;
}
if (bubbleOptions.mix) {
particle.bubble.color = undefined;
const pColor = particle.getFillColor();
particle.bubble.color = pColor ? (0,engine_root_window_.rgbToHsl)((0,engine_root_window_.colorMix)(pColor, particle.bubble.finalColor, 1 - ratio, ratio)) : particle.bubble.finalColor;
} else {
particle.bubble.color = particle.bubble.finalColor;
}
};
this._hoverBubbleOpacity = (particle, ratio, divBubble) => {
const container = this.container,
options = container.actualOptions,
modeOpacity = divBubble?.opacity ?? options.interactivity.modes.bubble?.opacity;
if (!modeOpacity) {
return;
}
const optOpacity = particle.options.opacity.value,
pOpacity = particle.opacity?.value ?? 1,
opacity = calculateBubbleValue(pOpacity, modeOpacity, (0,engine_root_window_.getRangeMax)(optOpacity), ratio);
if (opacity !== undefined) {
particle.bubble.opacity = opacity;
}
};
this._hoverBubbleSize = (particle, ratio, divBubble) => {
const container = this.container,
modeSize = divBubble?.size ? divBubble.size * container.retina.pixelRatio : container.retina.bubbleModeSize;
if (modeSize === undefined) {
return;
}
const optSize = (0,engine_root_window_.getRangeMax)(particle.options.size.value) * container.retina.pixelRatio,
pSize = particle.size.value,
size = calculateBubbleValue(pSize, modeSize, optSize, ratio);
if (size !== undefined) {
particle.bubble.radius = size;
}
};
this._process = (particle, distMouse, timeSpent, data) => {
const container = this.container,
bubbleParam = data.bubbleObj.optValue,
options = container.actualOptions,
bubbleOptions = options.interactivity.modes.bubble;
if (!bubbleOptions || bubbleParam === undefined) {
return;
}
const bubbleDuration = bubbleOptions.duration,
bubbleDistance = container.retina.bubbleModeDistance,
particlesParam = data.particlesObj.optValue,
pObjBubble = data.bubbleObj.value,
pObj = data.particlesObj.value || 0,
type = data.type;
if (!bubbleDistance || bubbleDistance < 0 || bubbleParam === particlesParam) {
return;
}
if (!container.bubble) {
container.bubble = {};
}
if (container.bubble.durationEnd) {
if (pObjBubble) {
if (type === "size") {
delete particle.bubble.radius;
}
if (type === "opacity") {
delete particle.bubble.opacity;
}
}
} else {
if (distMouse <= bubbleDistance) {
const obj = pObjBubble ?? pObj;
if (obj !== bubbleParam) {
const value = pObj - timeSpent * (pObj - bubbleParam) / bubbleDuration;
if (type === "size") {
particle.bubble.radius = value;
}
if (type === "opacity") {
particle.bubble.opacity = value;
}
}
} else {
if (type === "size") {
delete particle.bubble.radius;
}
if (type === "opacity") {
delete particle.bubble.opacity;
}
}
}
};
this._singleSelectorHover = (delta, selector, div) => {
const container = this.container,
selectors = document.querySelectorAll(selector),
bubble = container.actualOptions.interactivity.modes.bubble;
if (!bubble || !selectors.length) {
return;
}
selectors.forEach(item => {
const elem = item,
pxRatio = container.retina.pixelRatio,
pos = {
x: (elem.offsetLeft + elem.offsetWidth / 2) * pxRatio,
y: (elem.offsetTop + elem.offsetHeight / 2) * pxRatio
},
repulseRadius = elem.offsetWidth / 2 * pxRatio,
area = div.type === "circle" ? new engine_root_window_.Circle(pos.x, pos.y, repulseRadius) : new engine_root_window_.Rectangle(elem.offsetLeft * pxRatio, elem.offsetTop * pxRatio, elem.offsetWidth * pxRatio, elem.offsetHeight * pxRatio),
query = container.particles.quadTree.query(area, p => this.isEnabled(p));
for (const particle of query) {
if (!area.contains(particle.getPosition())) {
continue;
}
particle.bubble.inRange = true;
const divs = bubble.divs,
divBubble = (0,engine_root_window_.divMode)(divs, elem);
if (!particle.bubble.div || particle.bubble.div !== elem) {
this.clear(particle, delta, true);
particle.bubble.div = elem;
}
this._hoverBubbleSize(particle, 1, divBubble);
this._hoverBubbleOpacity(particle, 1, divBubble);
this._hoverBubbleColor(particle, 1, divBubble);
}
});
};
if (!container.bubble) {

@@ -248,23 +470,24 @@ container.bubble = {};

if (hoverEnabled && (0,engine_root_window_.isInArray)("bubble", hoverMode)) {
this.hoverBubble(delta);
this._hoverBubble();
} else if (clickEnabled && (0,engine_root_window_.isInArray)("bubble", clickMode)) {
this.clickBubble(delta);
this._clickBubble();
} else {
(0,engine_root_window_.divModeExecute)("bubble", divs, (selector, div) => this.singleSelectorHover(delta, selector, div));
(0,engine_root_window_.divModeExecute)("bubble", divs, (selector, div) => this._singleSelectorHover(delta, selector, div));
}
}
isEnabled(particle) {
var _a;
const container = this.container,
options = container.actualOptions,
mouse = container.interactivity.mouse,
events = ((_a = particle === null || particle === void 0 ? void 0 : particle.interactivity) !== null && _a !== void 0 ? _a : options.interactivity).events,
divs = events.onDiv,
divBubble = (0,engine_root_window_.isDivModeEnabled)("bubble", divs);
if (!(divBubble || events.onHover.enable && mouse.position || events.onClick.enable && mouse.clickPosition)) {
events = (particle?.interactivity ?? options.interactivity).events,
{
onClick,
onDiv,
onHover
} = events,
divBubble = (0,engine_root_window_.isDivModeEnabled)("bubble", onDiv);
if (!(divBubble || onHover.enable && mouse.position || onClick.enable && mouse.clickPosition)) {
return false;
}
const hoverMode = events.onHover.mode;
const clickMode = events.onClick.mode;
return (0,engine_root_window_.isInArray)("bubble", hoverMode) || (0,engine_root_window_.isInArray)("bubble", clickMode) || divBubble;
return (0,engine_root_window_.isInArray)("bubble", onHover.mode) || (0,engine_root_window_.isInArray)("bubble", onClick.mode) || divBubble;
}

@@ -276,3 +499,3 @@ loadModeOptions(options, ...sources) {

for (const source of sources) {
options.bubble.load(source === null || source === void 0 ? void 0 : source.bubble);
options.bubble.load(source?.bubble);
}

@@ -283,237 +506,7 @@ }

}
clickBubble(delta) {
var _a, _b;
const container = this.container,
options = container.actualOptions,
mouseClickPos = container.interactivity.mouse.clickPosition,
bubble = options.interactivity.modes.bubble;
if (!bubble || !mouseClickPos) {
return;
}
if (!container.bubble) {
container.bubble = {};
}
const distance = container.retina.bubbleModeDistance;
if (!distance || distance < 0) {
return;
}
const query = container.particles.quadTree.queryCircle(mouseClickPos, distance, p => this.isEnabled(p));
for (const particle of query) {
if (!container.bubble.clicking) {
continue;
}
particle.bubble.inRange = !container.bubble.durationEnd;
const pos = particle.getPosition(),
distMouse = (0,engine_root_window_.getDistance)(pos, mouseClickPos),
timeSpent = (new Date().getTime() - (container.interactivity.mouse.clickTime || 0)) / 1000;
if (timeSpent > bubble.duration) {
container.bubble.durationEnd = true;
}
if (timeSpent > bubble.duration * 2) {
container.bubble.clicking = false;
container.bubble.durationEnd = false;
}
const sizeData = {
bubbleObj: {
optValue: container.retina.bubbleModeSize,
value: particle.bubble.radius
},
particlesObj: {
optValue: (0,engine_root_window_.getRangeMax)(particle.options.size.value) * container.retina.pixelRatio,
value: particle.size.value
},
type: "size"
};
this.process(particle, distMouse, timeSpent, sizeData);
const opacityData = {
bubbleObj: {
optValue: bubble.opacity,
value: particle.bubble.opacity
},
particlesObj: {
optValue: (0,engine_root_window_.getRangeMax)(particle.options.opacity.value),
value: (_b = (_a = particle.opacity) === null || _a === void 0 ? void 0 : _a.value) !== null && _b !== void 0 ? _b : 1
},
type: "opacity"
};
this.process(particle, distMouse, timeSpent, opacityData);
if (!container.bubble.durationEnd) {
if (distMouse <= distance) {
this.hoverBubbleColor(particle, distMouse);
} else {
delete particle.bubble.color;
}
} else {
delete particle.bubble.color;
}
}
}
hoverBubble(delta) {
const container = this.container,
mousePos = container.interactivity.mouse.position,
distance = container.retina.bubbleModeDistance;
if (!distance || distance < 0 || mousePos === undefined) {
return;
}
const query = container.particles.quadTree.queryCircle(mousePos, distance, p => this.isEnabled(p));
for (const particle of query) {
particle.bubble.inRange = true;
const pos = particle.getPosition(),
pointDistance = (0,engine_root_window_.getDistance)(pos, mousePos),
ratio = 1 - pointDistance / distance;
if (pointDistance <= distance) {
if (ratio >= 0 && container.interactivity.status === engine_root_window_.mouseMoveEvent) {
this.hoverBubbleSize(particle, ratio);
this.hoverBubbleOpacity(particle, ratio);
this.hoverBubbleColor(particle, ratio);
}
} else {
this.reset(particle);
}
if (container.interactivity.status === engine_root_window_.mouseLeaveEvent) {
this.reset(particle);
}
}
}
hoverBubbleColor(particle, ratio, divBubble) {
const options = this.container.actualOptions;
const bubbleOptions = divBubble !== null && divBubble !== void 0 ? divBubble : options.interactivity.modes.bubble;
if (!bubbleOptions) {
return;
}
if (!particle.bubble.finalColor) {
const modeColor = bubbleOptions.color;
if (!modeColor) {
return;
}
const bubbleColor = (0,engine_root_window_.itemFromSingleOrMultiple)(modeColor);
particle.bubble.finalColor = (0,engine_root_window_.rangeColorToHsl)(bubbleColor);
}
if (!particle.bubble.finalColor) {
return;
}
if (bubbleOptions.mix) {
particle.bubble.color = undefined;
const pColor = particle.getFillColor();
particle.bubble.color = pColor ? (0,engine_root_window_.rgbToHsl)((0,engine_root_window_.colorMix)(pColor, particle.bubble.finalColor, 1 - ratio, ratio)) : particle.bubble.finalColor;
} else {
particle.bubble.color = particle.bubble.finalColor;
}
}
hoverBubbleOpacity(particle, ratio, divBubble) {
var _a, _b, _c, _d;
const container = this.container,
options = container.actualOptions,
modeOpacity = (_a = divBubble === null || divBubble === void 0 ? void 0 : divBubble.opacity) !== null && _a !== void 0 ? _a : (_b = options.interactivity.modes.bubble) === null || _b === void 0 ? void 0 : _b.opacity;
if (!modeOpacity) {
return;
}
const optOpacity = particle.options.opacity.value;
const pOpacity = (_d = (_c = particle.opacity) === null || _c === void 0 ? void 0 : _c.value) !== null && _d !== void 0 ? _d : 1;
const opacity = calculateBubbleValue(pOpacity, modeOpacity, (0,engine_root_window_.getRangeMax)(optOpacity), ratio);
if (opacity !== undefined) {
particle.bubble.opacity = opacity;
}
}
hoverBubbleSize(particle, ratio, divBubble) {
const container = this.container,
modeSize = (divBubble === null || divBubble === void 0 ? void 0 : divBubble.size) ? divBubble.size * container.retina.pixelRatio : container.retina.bubbleModeSize;
if (modeSize === undefined) {
return;
}
const optSize = (0,engine_root_window_.getRangeMax)(particle.options.size.value) * container.retina.pixelRatio;
const pSize = particle.size.value;
const size = calculateBubbleValue(pSize, modeSize, optSize, ratio);
if (size !== undefined) {
particle.bubble.radius = size;
}
}
process(particle, distMouse, timeSpent, data) {
const container = this.container,
bubbleParam = data.bubbleObj.optValue,
options = container.actualOptions,
bubble = options.interactivity.modes.bubble;
if (!bubble || bubbleParam === undefined) {
return;
}
const bubbleDuration = bubble.duration,
bubbleDistance = container.retina.bubbleModeDistance,
particlesParam = data.particlesObj.optValue,
pObjBubble = data.bubbleObj.value,
pObj = data.particlesObj.value || 0,
type = data.type;
if (!bubbleDistance || bubbleDistance < 0 || bubbleParam === particlesParam) {
return;
}
if (!container.bubble) {
container.bubble = {};
}
if (!container.bubble.durationEnd) {
if (distMouse <= bubbleDistance) {
const obj = pObjBubble !== null && pObjBubble !== void 0 ? pObjBubble : pObj;
if (obj !== bubbleParam) {
const value = pObj - timeSpent * (pObj - bubbleParam) / bubbleDuration;
if (type === "size") {
particle.bubble.radius = value;
}
if (type === "opacity") {
particle.bubble.opacity = value;
}
}
} else {
if (type === "size") {
delete particle.bubble.radius;
}
if (type === "opacity") {
delete particle.bubble.opacity;
}
}
} else if (pObjBubble) {
if (type === "size") {
delete particle.bubble.radius;
}
if (type === "opacity") {
delete particle.bubble.opacity;
}
}
}
singleSelectorHover(delta, selector, div) {
const container = this.container,
selectors = document.querySelectorAll(selector),
bubble = container.actualOptions.interactivity.modes.bubble;
if (!bubble || !selectors.length) {
return;
}
selectors.forEach(item => {
const elem = item,
pxRatio = container.retina.pixelRatio,
pos = {
x: (elem.offsetLeft + elem.offsetWidth / 2) * pxRatio,
y: (elem.offsetTop + elem.offsetHeight / 2) * pxRatio
},
repulseRadius = elem.offsetWidth / 2 * pxRatio,
area = div.type === "circle" ? new engine_root_window_.Circle(pos.x, pos.y, repulseRadius) : new engine_root_window_.Rectangle(elem.offsetLeft * pxRatio, elem.offsetTop * pxRatio, elem.offsetWidth * pxRatio, elem.offsetHeight * pxRatio),
query = container.particles.quadTree.query(area, p => this.isEnabled(p));
for (const particle of query) {
if (!area.contains(particle.getPosition())) {
continue;
}
particle.bubble.inRange = true;
const divs = bubble.divs;
const divBubble = (0,engine_root_window_.divMode)(divs, elem);
if (!particle.bubble.div || particle.bubble.div !== elem) {
this.clear(particle, delta, true);
particle.bubble.div = elem;
}
this.hoverBubbleSize(particle, 1, divBubble);
this.hoverBubbleOpacity(particle, 1, divBubble);
this.hoverBubbleColor(particle, 1, divBubble);
}
});
}
}
;// CONCATENATED MODULE: ./dist/browser/index.js
async function loadExternalBubbleInteraction(engine) {
await engine.addInteractor("externalBubble", container => new Bubbler(container));
async function loadExternalBubbleInteraction(engine, refresh = true) {
await engine.addInteractor("externalBubble", container => new Bubbler(container), refresh);
}

@@ -520,0 +513,0 @@

/*! For license information please see tsparticles.interaction.external.bubble.min.js.LICENSE.txt */
!function(e,t){if("object"==typeof exports&&"object"==typeof module)module.exports=t(require("@tsparticles/engine"));else if("function"==typeof define&&define.amd)define(["@tsparticles/engine"],t);else{var i="object"==typeof exports?t(require("@tsparticles/engine")):t(e.window);for(var o in i)("object"==typeof exports?exports:e)[o]=i[o]}}(this,(e=>(()=>{"use strict";var t={533:t=>{t.exports=e}},i={};function o(e){var l=i[e];if(void 0!==l)return l.exports;var b=i[e]={exports:{}};return t[e](b,b.exports,o),b.exports}o.d=(e,t)=>{for(var i in t)o.o(t,i)&&!o.o(e,i)&&Object.defineProperty(e,i,{enumerable:!0,get:t[i]})},o.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),o.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})};var l={};return(()=>{o.r(l),o.d(l,{Bubble:()=>b,BubbleBase:()=>t,BubbleDiv:()=>i,loadExternalBubbleInteraction:()=>r});var e=o(533);class t{constructor(){this.distance=200,this.duration=.4,this.mix=!1}load(t){if(t){if(void 0!==t.distance&&(this.distance=t.distance),void 0!==t.duration&&(this.duration=t.duration),void 0!==t.mix&&(this.mix=t.mix),void 0!==t.opacity&&(this.opacity=t.opacity),void 0!==t.color){const i=this.color instanceof Array?void 0:this.color;this.color=(0,e.executeOnSingleOrMultiple)(t.color,(t=>e.OptionsColor.create(i,t)))}void 0!==t.size&&(this.size=t.size)}}}class i extends t{constructor(){super(),this.selectors=[]}get ids(){return(0,e.executeOnSingleOrMultiple)(this.selectors,(e=>e.replace("#","")))}set ids(t){this.selectors=(0,e.executeOnSingleOrMultiple)(t,(e=>`#${e}`))}load(e){super.load(e),e&&(void 0!==e.ids&&(this.ids=e.ids),void 0!==e.selectors&&(this.selectors=e.selectors))}}class b extends t{load(t){super.load(t),t&&(this.divs=(0,e.executeOnSingleOrMultiple)(t.divs,(e=>{const t=new i;return t.load(e),t})))}}function n(t,i,o,l){if(i>=o){const b=t+(i-o)*l;return(0,e.clamp)(b,t,i)}if(i<o){const b=t-(o-i)*l;return(0,e.clamp)(b,i,t)}}class s extends e.ExternalInteractorBase{constructor(e){super(e),e.bubble||(e.bubble={}),this.handleClickMode=t=>{"bubble"===t&&(e.bubble||(e.bubble={}),e.bubble.clicking=!0)}}clear(e,t,i){e.bubble.inRange&&!i||(delete e.bubble.div,delete e.bubble.opacity,delete e.bubble.radius,delete e.bubble.color)}init(){const e=this.container,t=e.actualOptions.interactivity.modes.bubble;t&&(e.retina.bubbleModeDistance=t.distance*e.retina.pixelRatio,void 0!==t.size&&(e.retina.bubbleModeSize=t.size*e.retina.pixelRatio))}async interact(t){const i=this.container.actualOptions.interactivity.events,o=i.onHover,l=i.onClick,b=o.enable,n=o.mode,s=l.enable,r=l.mode,a=i.onDiv;b&&(0,e.isInArray)("bubble",n)?this.hoverBubble(t):s&&(0,e.isInArray)("bubble",r)?this.clickBubble(t):(0,e.divModeExecute)("bubble",a,((e,i)=>this.singleSelectorHover(t,e,i)))}isEnabled(t){var i;const o=this.container,l=o.actualOptions,b=o.interactivity.mouse,n=(null!==(i=null==t?void 0:t.interactivity)&&void 0!==i?i:l.interactivity).events,s=n.onDiv,r=(0,e.isDivModeEnabled)("bubble",s);if(!(r||n.onHover.enable&&b.position||n.onClick.enable&&b.clickPosition))return!1;const a=n.onHover.mode,u=n.onClick.mode;return(0,e.isInArray)("bubble",a)||(0,e.isInArray)("bubble",u)||r}loadModeOptions(e,...t){e.bubble||(e.bubble=new b);for(const i of t)e.bubble.load(null==i?void 0:i.bubble)}reset(e){e.bubble.inRange=!1}clickBubble(t){var i,o;const l=this.container,b=l.actualOptions,n=l.interactivity.mouse.clickPosition,s=b.interactivity.modes.bubble;if(!s||!n)return;l.bubble||(l.bubble={});const r=l.retina.bubbleModeDistance;if(!r||r<0)return;const a=l.particles.quadTree.queryCircle(n,r,(e=>this.isEnabled(e)));for(const t of a){if(!l.bubble.clicking)continue;t.bubble.inRange=!l.bubble.durationEnd;const b=t.getPosition(),a=(0,e.getDistance)(b,n),u=((new Date).getTime()-(l.interactivity.mouse.clickTime||0))/1e3;u>s.duration&&(l.bubble.durationEnd=!0),u>2*s.duration&&(l.bubble.clicking=!1,l.bubble.durationEnd=!1);const c={bubbleObj:{optValue:l.retina.bubbleModeSize,value:t.bubble.radius},particlesObj:{optValue:(0,e.getRangeMax)(t.options.size.value)*l.retina.pixelRatio,value:t.size.value},type:"size"};this.process(t,a,u,c);const d={bubbleObj:{optValue:s.opacity,value:t.bubble.opacity},particlesObj:{optValue:(0,e.getRangeMax)(t.options.opacity.value),value:null!==(o=null===(i=t.opacity)||void 0===i?void 0:i.value)&&void 0!==o?o:1},type:"opacity"};this.process(t,a,u,d),l.bubble.durationEnd?delete t.bubble.color:a<=r?this.hoverBubbleColor(t,a):delete t.bubble.color}}hoverBubble(t){const i=this.container,o=i.interactivity.mouse.position,l=i.retina.bubbleModeDistance;if(!l||l<0||void 0===o)return;const b=i.particles.quadTree.queryCircle(o,l,(e=>this.isEnabled(e)));for(const t of b){t.bubble.inRange=!0;const b=t.getPosition(),n=(0,e.getDistance)(b,o),s=1-n/l;n<=l?s>=0&&i.interactivity.status===e.mouseMoveEvent&&(this.hoverBubbleSize(t,s),this.hoverBubbleOpacity(t,s),this.hoverBubbleColor(t,s)):this.reset(t),i.interactivity.status===e.mouseLeaveEvent&&this.reset(t)}}hoverBubbleColor(t,i,o){const l=this.container.actualOptions,b=null!=o?o:l.interactivity.modes.bubble;if(b){if(!t.bubble.finalColor){const i=b.color;if(!i)return;const o=(0,e.itemFromSingleOrMultiple)(i);t.bubble.finalColor=(0,e.rangeColorToHsl)(o)}if(t.bubble.finalColor)if(b.mix){t.bubble.color=void 0;const o=t.getFillColor();t.bubble.color=o?(0,e.rgbToHsl)((0,e.colorMix)(o,t.bubble.finalColor,1-i,i)):t.bubble.finalColor}else t.bubble.color=t.bubble.finalColor}}hoverBubbleOpacity(t,i,o){var l,b,s,r;const a=this.container.actualOptions,u=null!==(l=null==o?void 0:o.opacity)&&void 0!==l?l:null===(b=a.interactivity.modes.bubble)||void 0===b?void 0:b.opacity;if(!u)return;const c=t.options.opacity.value,d=n(null!==(r=null===(s=t.opacity)||void 0===s?void 0:s.value)&&void 0!==r?r:1,u,(0,e.getRangeMax)(c),i);void 0!==d&&(t.bubble.opacity=d)}hoverBubbleSize(t,i,o){const l=this.container,b=(null==o?void 0:o.size)?o.size*l.retina.pixelRatio:l.retina.bubbleModeSize;if(void 0===b)return;const s=(0,e.getRangeMax)(t.options.size.value)*l.retina.pixelRatio,r=n(t.size.value,b,s,i);void 0!==r&&(t.bubble.radius=r)}process(e,t,i,o){const l=this.container,b=o.bubbleObj.optValue,n=l.actualOptions.interactivity.modes.bubble;if(!n||void 0===b)return;const s=n.duration,r=l.retina.bubbleModeDistance,a=o.particlesObj.optValue,u=o.bubbleObj.value,c=o.particlesObj.value||0,d=o.type;if(r&&!(r<0)&&b!==a)if(l.bubble||(l.bubble={}),l.bubble.durationEnd)u&&("size"===d&&delete e.bubble.radius,"opacity"===d&&delete e.bubble.opacity);else if(t<=r){if((null!=u?u:c)!==b){const t=c-i*(c-b)/s;"size"===d&&(e.bubble.radius=t),"opacity"===d&&(e.bubble.opacity=t)}}else"size"===d&&delete e.bubble.radius,"opacity"===d&&delete e.bubble.opacity}singleSelectorHover(t,i,o){const l=this.container,b=document.querySelectorAll(i),n=l.actualOptions.interactivity.modes.bubble;n&&b.length&&b.forEach((i=>{const b=i,s=l.retina.pixelRatio,r={x:(b.offsetLeft+b.offsetWidth/2)*s,y:(b.offsetTop+b.offsetHeight/2)*s},a=b.offsetWidth/2*s,u="circle"===o.type?new e.Circle(r.x,r.y,a):new e.Rectangle(b.offsetLeft*s,b.offsetTop*s,b.offsetWidth*s,b.offsetHeight*s),c=l.particles.quadTree.query(u,(e=>this.isEnabled(e)));for(const i of c){if(!u.contains(i.getPosition()))continue;i.bubble.inRange=!0;const o=n.divs,l=(0,e.divMode)(o,b);i.bubble.div&&i.bubble.div===b||(this.clear(i,t,!0),i.bubble.div=b),this.hoverBubbleSize(i,1,l),this.hoverBubbleOpacity(i,1,l),this.hoverBubbleColor(i,1,l)}}))}}async function r(e){await e.addInteractor("externalBubble",(e=>new s(e)))}})(),l})()));
!function(e,t){if("object"==typeof exports&&"object"==typeof module)module.exports=t(require("@tsparticles/engine"));else if("function"==typeof define&&define.amd)define(["@tsparticles/engine"],t);else{var i="object"==typeof exports?t(require("@tsparticles/engine")):t(e.window);for(var o in i)("object"==typeof exports?exports:e)[o]=i[o]}}(this,(e=>(()=>{"use strict";var t={533:t=>{t.exports=e}},i={};function o(e){var b=i[e];if(void 0!==b)return b.exports;var n=i[e]={exports:{}};return t[e](n,n.exports,o),n.exports}o.d=(e,t)=>{for(var i in t)o.o(t,i)&&!o.o(e,i)&&Object.defineProperty(e,i,{enumerable:!0,get:t[i]})},o.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),o.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})};var b={};return(()=>{o.r(b),o.d(b,{Bubble:()=>n,BubbleBase:()=>t,BubbleDiv:()=>i,loadExternalBubbleInteraction:()=>r});var e=o(533);class t{constructor(){this.distance=200,this.duration=.4,this.mix=!1}load(t){if(t){if(void 0!==t.distance&&(this.distance=t.distance),void 0!==t.duration&&(this.duration=t.duration),void 0!==t.mix&&(this.mix=t.mix),void 0!==t.opacity&&(this.opacity=t.opacity),void 0!==t.color){const i=(0,e.isArray)(this.color)?void 0:this.color;this.color=(0,e.executeOnSingleOrMultiple)(t.color,(t=>e.OptionsColor.create(i,t)))}void 0!==t.size&&(this.size=t.size)}}}class i extends t{constructor(){super(),this.selectors=[]}load(e){super.load(e),e&&void 0!==e.selectors&&(this.selectors=e.selectors)}}class n extends t{load(t){super.load(t),t&&(this.divs=(0,e.executeOnSingleOrMultiple)(t.divs,(e=>{const t=new i;return t.load(e),t})))}}function l(t,i,o,b){if(i>=o){const n=t+(i-o)*b;return(0,e.clamp)(n,t,i)}if(i<o){const n=t-(o-i)*b;return(0,e.clamp)(n,i,t)}}class s extends e.ExternalInteractorBase{constructor(t){super(t),this._clickBubble=()=>{const t=this.container,i=t.actualOptions,o=t.interactivity.mouse.clickPosition,b=i.interactivity.modes.bubble;if(!b||!o)return;t.bubble||(t.bubble={});const n=t.retina.bubbleModeDistance;if(!n||n<0)return;const l=t.particles.quadTree.queryCircle(o,n,(e=>this.isEnabled(e))),{bubble:s}=t;for(const i of l){if(!s.clicking)continue;i.bubble.inRange=!s.durationEnd;const l=i.getPosition(),r=(0,e.getDistance)(l,o),a=((new Date).getTime()-(t.interactivity.mouse.clickTime||0))/1e3;a>b.duration&&(s.durationEnd=!0),a>2*b.duration&&(s.clicking=!1,s.durationEnd=!1);const c={bubbleObj:{optValue:t.retina.bubbleModeSize,value:i.bubble.radius},particlesObj:{optValue:(0,e.getRangeMax)(i.options.size.value)*t.retina.pixelRatio,value:i.size.value},type:"size"};this._process(i,r,a,c);const u={bubbleObj:{optValue:b.opacity,value:i.bubble.opacity},particlesObj:{optValue:(0,e.getRangeMax)(i.options.opacity.value),value:i.opacity?.value??1},type:"opacity"};this._process(i,r,a,u),!s.durationEnd&&r<=n?this._hoverBubbleColor(i,r):delete i.bubble.color}},this._hoverBubble=()=>{const t=this.container,i=t.interactivity.mouse.position,o=t.retina.bubbleModeDistance;if(!o||o<0||void 0===i)return;const b=t.particles.quadTree.queryCircle(i,o,(e=>this.isEnabled(e)));for(const n of b){n.bubble.inRange=!0;const b=n.getPosition(),l=(0,e.getDistance)(b,i),s=1-l/o;l<=o?s>=0&&t.interactivity.status===e.mouseMoveEvent&&(this._hoverBubbleSize(n,s),this._hoverBubbleOpacity(n,s),this._hoverBubbleColor(n,s)):this.reset(n),t.interactivity.status===e.mouseLeaveEvent&&this.reset(n)}},this._hoverBubbleColor=(t,i,o)=>{const b=this.container.actualOptions,n=o??b.interactivity.modes.bubble;if(n){if(!t.bubble.finalColor){const i=n.color;if(!i)return;const o=(0,e.itemFromSingleOrMultiple)(i);t.bubble.finalColor=(0,e.rangeColorToHsl)(o)}if(t.bubble.finalColor)if(n.mix){t.bubble.color=void 0;const o=t.getFillColor();t.bubble.color=o?(0,e.rgbToHsl)((0,e.colorMix)(o,t.bubble.finalColor,1-i,i)):t.bubble.finalColor}else t.bubble.color=t.bubble.finalColor}},this._hoverBubbleOpacity=(t,i,o)=>{const b=this.container.actualOptions,n=o?.opacity??b.interactivity.modes.bubble?.opacity;if(!n)return;const s=t.options.opacity.value,r=l(t.opacity?.value??1,n,(0,e.getRangeMax)(s),i);void 0!==r&&(t.bubble.opacity=r)},this._hoverBubbleSize=(t,i,o)=>{const b=this.container,n=o?.size?o.size*b.retina.pixelRatio:b.retina.bubbleModeSize;if(void 0===n)return;const s=(0,e.getRangeMax)(t.options.size.value)*b.retina.pixelRatio,r=l(t.size.value,n,s,i);void 0!==r&&(t.bubble.radius=r)},this._process=(e,t,i,o)=>{const b=this.container,n=o.bubbleObj.optValue,l=b.actualOptions.interactivity.modes.bubble;if(!l||void 0===n)return;const s=l.duration,r=b.retina.bubbleModeDistance,a=o.particlesObj.optValue,c=o.bubbleObj.value,u=o.particlesObj.value||0,d=o.type;if(r&&!(r<0)&&n!==a)if(b.bubble||(b.bubble={}),b.bubble.durationEnd)c&&("size"===d&&delete e.bubble.radius,"opacity"===d&&delete e.bubble.opacity);else if(t<=r){if((c??u)!==n){const t=u-i*(u-n)/s;"size"===d&&(e.bubble.radius=t),"opacity"===d&&(e.bubble.opacity=t)}}else"size"===d&&delete e.bubble.radius,"opacity"===d&&delete e.bubble.opacity},this._singleSelectorHover=(t,i,o)=>{const b=this.container,n=document.querySelectorAll(i),l=b.actualOptions.interactivity.modes.bubble;l&&n.length&&n.forEach((i=>{const n=i,s=b.retina.pixelRatio,r={x:(n.offsetLeft+n.offsetWidth/2)*s,y:(n.offsetTop+n.offsetHeight/2)*s},a=n.offsetWidth/2*s,c="circle"===o.type?new e.Circle(r.x,r.y,a):new e.Rectangle(n.offsetLeft*s,n.offsetTop*s,n.offsetWidth*s,n.offsetHeight*s),u=b.particles.quadTree.query(c,(e=>this.isEnabled(e)));for(const i of u){if(!c.contains(i.getPosition()))continue;i.bubble.inRange=!0;const o=l.divs,b=(0,e.divMode)(o,n);i.bubble.div&&i.bubble.div===n||(this.clear(i,t,!0),i.bubble.div=n),this._hoverBubbleSize(i,1,b),this._hoverBubbleOpacity(i,1,b),this._hoverBubbleColor(i,1,b)}}))},t.bubble||(t.bubble={}),this.handleClickMode=e=>{"bubble"===e&&(t.bubble||(t.bubble={}),t.bubble.clicking=!0)}}clear(e,t,i){e.bubble.inRange&&!i||(delete e.bubble.div,delete e.bubble.opacity,delete e.bubble.radius,delete e.bubble.color)}init(){const e=this.container,t=e.actualOptions.interactivity.modes.bubble;t&&(e.retina.bubbleModeDistance=t.distance*e.retina.pixelRatio,void 0!==t.size&&(e.retina.bubbleModeSize=t.size*e.retina.pixelRatio))}async interact(t){const i=this.container.actualOptions.interactivity.events,o=i.onHover,b=i.onClick,n=o.enable,l=o.mode,s=b.enable,r=b.mode,a=i.onDiv;n&&(0,e.isInArray)("bubble",l)?this._hoverBubble():s&&(0,e.isInArray)("bubble",r)?this._clickBubble():(0,e.divModeExecute)("bubble",a,((e,i)=>this._singleSelectorHover(t,e,i)))}isEnabled(t){const i=this.container,o=i.actualOptions,b=i.interactivity.mouse,n=(t?.interactivity??o.interactivity).events,{onClick:l,onDiv:s,onHover:r}=n,a=(0,e.isDivModeEnabled)("bubble",s);return!!(a||r.enable&&b.position||l.enable&&b.clickPosition)&&((0,e.isInArray)("bubble",r.mode)||(0,e.isInArray)("bubble",l.mode)||a)}loadModeOptions(e,...t){e.bubble||(e.bubble=new n);for(const i of t)e.bubble.load(i?.bubble)}reset(e){e.bubble.inRange=!1}}async function r(e,t=!0){await e.addInteractor("externalBubble",(e=>new s(e)),t)}})(),b})()));

@@ -1,8 +0,1 @@

/*!
* Author : Matteo Bruni
* MIT license: https://opensource.org/licenses/MIT
* Demo / Generator : https://particles.js.org/
* GitHub : https://www.github.com/matteobruni/tsparticles
* How to use? : Check the GitHub README
* v3.0.0-alpha.1
*/
/*! tsParticles Bubble External Interaction v3.0.0-beta.0 by Matteo Bruni */
import type { BubbleContainer, BubbleMode, IBubbleMode } from "./Types";
import { ClickMode, ExternalInteractorBase } from "@tsparticles/engine";
import type { IDelta, IModes, Modes, Particle, RecursivePartial } from "@tsparticles/engine";
import { ClickMode, ExternalInteractorBase, type IDelta, type IModes, type Modes, type Particle, type RecursivePartial } from "@tsparticles/engine";
export declare class Bubbler extends ExternalInteractorBase<BubbleContainer> {

@@ -13,9 +12,9 @@ handleClickMode: (mode: ClickMode | string) => void;

reset(particle: Particle): void;
private clickBubble;
private hoverBubble;
private hoverBubbleColor;
private hoverBubbleOpacity;
private hoverBubbleSize;
private process;
private singleSelectorHover;
private readonly _clickBubble;
private readonly _hoverBubble;
private readonly _hoverBubbleColor;
private readonly _hoverBubbleOpacity;
private readonly _hoverBubbleSize;
private readonly _process;
private readonly _singleSelectorHover;
}
import type { Engine } from "@tsparticles/engine";
export declare function loadExternalBubbleInteraction(engine: Engine): Promise<void>;
export declare function loadExternalBubbleInteraction(engine: Engine, refresh?: boolean): Promise<void>;
export * from "./Options/Classes/BubbleBase";

@@ -4,0 +4,0 @@ export * from "./Options/Classes/BubbleDiv";

@@ -1,2 +0,2 @@

import type { IOptionLoader, RecursivePartial, SingleOrMultiple } from "@tsparticles/engine";
import { type IOptionLoader, type RecursivePartial, type SingleOrMultiple } from "@tsparticles/engine";
import { BubbleBase } from "./BubbleBase";

@@ -3,0 +3,0 @@ import { BubbleDiv } from "./BubbleDiv";

@@ -1,3 +0,2 @@

import type { IOptionLoader, RecursivePartial, SingleOrMultiple } from "@tsparticles/engine";
import { OptionsColor } from "@tsparticles/engine";
import { type IOptionLoader, OptionsColor, type RecursivePartial, type SingleOrMultiple } from "@tsparticles/engine";
import type { IBubbleBase } from "../Interfaces/IBubbleBase";

@@ -4,0 +3,0 @@ export declare abstract class BubbleBase implements IBubbleBase, IOptionLoader<IBubbleBase> {

@@ -1,2 +0,2 @@

import type { IOptionLoader, RecursivePartial, SingleOrMultiple } from "@tsparticles/engine";
import { type IOptionLoader, type RecursivePartial, type SingleOrMultiple } from "@tsparticles/engine";
import { BubbleBase } from "./BubbleBase";

@@ -7,5 +7,3 @@ import type { IBubbleDiv } from "../Interfaces/IBubbleDiv";

constructor();
get ids(): SingleOrMultiple<string>;
set ids(value: SingleOrMultiple<string>);
load(data?: RecursivePartial<IBubbleDiv>): void;
}

@@ -7,3 +7,3 @@ (function (factory) {

else if (typeof define === "function" && define.amd) {
define(["require", "exports", "@tsparticles/engine", "./Options/Classes/Bubble"], factory);
define(["require", "exports", "@tsparticles/engine", "./Options/Classes/Bubble", "./Utils"], factory);
}

@@ -16,15 +16,208 @@ })(function (require, exports) {

const Bubble_1 = require("./Options/Classes/Bubble");
function calculateBubbleValue(particleValue, modeValue, optionsValue, ratio) {
if (modeValue >= optionsValue) {
const value = particleValue + (modeValue - optionsValue) * ratio;
return (0, engine_1.clamp)(value, particleValue, modeValue);
}
else if (modeValue < optionsValue) {
const value = particleValue - (optionsValue - modeValue) * ratio;
return (0, engine_1.clamp)(value, modeValue, particleValue);
}
}
const Utils_1 = require("./Utils");
class Bubbler extends engine_1.ExternalInteractorBase {
constructor(container) {
super(container);
this._clickBubble = () => {
const container = this.container, options = container.actualOptions, mouseClickPos = container.interactivity.mouse.clickPosition, bubbleOptions = options.interactivity.modes.bubble;
if (!bubbleOptions || !mouseClickPos) {
return;
}
if (!container.bubble) {
container.bubble = {};
}
const distance = container.retina.bubbleModeDistance;
if (!distance || distance < 0) {
return;
}
const query = container.particles.quadTree.queryCircle(mouseClickPos, distance, (p) => this.isEnabled(p)), { bubble } = container;
for (const particle of query) {
if (!bubble.clicking) {
continue;
}
particle.bubble.inRange = !bubble.durationEnd;
const pos = particle.getPosition(), distMouse = (0, engine_1.getDistance)(pos, mouseClickPos), timeSpent = (new Date().getTime() - (container.interactivity.mouse.clickTime || 0)) / 1000;
if (timeSpent > bubbleOptions.duration) {
bubble.durationEnd = true;
}
if (timeSpent > bubbleOptions.duration * 2) {
bubble.clicking = false;
bubble.durationEnd = false;
}
const sizeData = {
bubbleObj: {
optValue: container.retina.bubbleModeSize,
value: particle.bubble.radius,
},
particlesObj: {
optValue: (0, engine_1.getRangeMax)(particle.options.size.value) * container.retina.pixelRatio,
value: particle.size.value,
},
type: "size",
};
this._process(particle, distMouse, timeSpent, sizeData);
const opacityData = {
bubbleObj: {
optValue: bubbleOptions.opacity,
value: particle.bubble.opacity,
},
particlesObj: {
optValue: (0, engine_1.getRangeMax)(particle.options.opacity.value),
value: particle.opacity?.value ?? 1,
},
type: "opacity",
};
this._process(particle, distMouse, timeSpent, opacityData);
if (!bubble.durationEnd && distMouse <= distance) {
this._hoverBubbleColor(particle, distMouse);
}
else {
delete particle.bubble.color;
}
}
};
this._hoverBubble = () => {
const container = this.container, mousePos = container.interactivity.mouse.position, distance = container.retina.bubbleModeDistance;
if (!distance || distance < 0 || mousePos === undefined) {
return;
}
const query = container.particles.quadTree.queryCircle(mousePos, distance, (p) => this.isEnabled(p));
for (const particle of query) {
particle.bubble.inRange = true;
const pos = particle.getPosition(), pointDistance = (0, engine_1.getDistance)(pos, mousePos), ratio = 1 - pointDistance / distance;
if (pointDistance <= distance) {
if (ratio >= 0 && container.interactivity.status === engine_1.mouseMoveEvent) {
this._hoverBubbleSize(particle, ratio);
this._hoverBubbleOpacity(particle, ratio);
this._hoverBubbleColor(particle, ratio);
}
}
else {
this.reset(particle);
}
if (container.interactivity.status === engine_1.mouseLeaveEvent) {
this.reset(particle);
}
}
};
this._hoverBubbleColor = (particle, ratio, divBubble) => {
const options = this.container.actualOptions, bubbleOptions = divBubble ?? options.interactivity.modes.bubble;
if (!bubbleOptions) {
return;
}
if (!particle.bubble.finalColor) {
const modeColor = bubbleOptions.color;
if (!modeColor) {
return;
}
const bubbleColor = (0, engine_1.itemFromSingleOrMultiple)(modeColor);
particle.bubble.finalColor = (0, engine_1.rangeColorToHsl)(bubbleColor);
}
if (!particle.bubble.finalColor) {
return;
}
if (bubbleOptions.mix) {
particle.bubble.color = undefined;
const pColor = particle.getFillColor();
particle.bubble.color = pColor
? (0, engine_1.rgbToHsl)((0, engine_1.colorMix)(pColor, particle.bubble.finalColor, 1 - ratio, ratio))
: particle.bubble.finalColor;
}
else {
particle.bubble.color = particle.bubble.finalColor;
}
};
this._hoverBubbleOpacity = (particle, ratio, divBubble) => {
const container = this.container, options = container.actualOptions, modeOpacity = divBubble?.opacity ?? options.interactivity.modes.bubble?.opacity;
if (!modeOpacity) {
return;
}
const optOpacity = particle.options.opacity.value, pOpacity = particle.opacity?.value ?? 1, opacity = (0, Utils_1.calculateBubbleValue)(pOpacity, modeOpacity, (0, engine_1.getRangeMax)(optOpacity), ratio);
if (opacity !== undefined) {
particle.bubble.opacity = opacity;
}
};
this._hoverBubbleSize = (particle, ratio, divBubble) => {
const container = this.container, modeSize = divBubble?.size ? divBubble.size * container.retina.pixelRatio : container.retina.bubbleModeSize;
if (modeSize === undefined) {
return;
}
const optSize = (0, engine_1.getRangeMax)(particle.options.size.value) * container.retina.pixelRatio, pSize = particle.size.value, size = (0, Utils_1.calculateBubbleValue)(pSize, modeSize, optSize, ratio);
if (size !== undefined) {
particle.bubble.radius = size;
}
};
this._process = (particle, distMouse, timeSpent, data) => {
const container = this.container, bubbleParam = data.bubbleObj.optValue, options = container.actualOptions, bubbleOptions = options.interactivity.modes.bubble;
if (!bubbleOptions || bubbleParam === undefined) {
return;
}
const bubbleDuration = bubbleOptions.duration, bubbleDistance = container.retina.bubbleModeDistance, particlesParam = data.particlesObj.optValue, pObjBubble = data.bubbleObj.value, pObj = data.particlesObj.value || 0, type = data.type;
if (!bubbleDistance || bubbleDistance < 0 || bubbleParam === particlesParam) {
return;
}
if (!container.bubble) {
container.bubble = {};
}
if (container.bubble.durationEnd) {
if (pObjBubble) {
if (type === "size") {
delete particle.bubble.radius;
}
if (type === "opacity") {
delete particle.bubble.opacity;
}
}
}
else {
if (distMouse <= bubbleDistance) {
const obj = pObjBubble ?? pObj;
if (obj !== bubbleParam) {
const value = pObj - (timeSpent * (pObj - bubbleParam)) / bubbleDuration;
if (type === "size") {
particle.bubble.radius = value;
}
if (type === "opacity") {
particle.bubble.opacity = value;
}
}
}
else {
if (type === "size") {
delete particle.bubble.radius;
}
if (type === "opacity") {
delete particle.bubble.opacity;
}
}
}
};
this._singleSelectorHover = (delta, selector, div) => {
const container = this.container, selectors = document.querySelectorAll(selector), bubble = container.actualOptions.interactivity.modes.bubble;
if (!bubble || !selectors.length) {
return;
}
selectors.forEach((item) => {
const elem = item, pxRatio = container.retina.pixelRatio, pos = {
x: (elem.offsetLeft + elem.offsetWidth / 2) * pxRatio,
y: (elem.offsetTop + elem.offsetHeight / 2) * pxRatio,
}, repulseRadius = (elem.offsetWidth / 2) * pxRatio, area = div.type === "circle"
? new engine_1.Circle(pos.x, pos.y, repulseRadius)
: new engine_1.Rectangle(elem.offsetLeft * pxRatio, elem.offsetTop * pxRatio, elem.offsetWidth * pxRatio, elem.offsetHeight * pxRatio), query = container.particles.quadTree.query(area, (p) => this.isEnabled(p));
for (const particle of query) {
if (!area.contains(particle.getPosition())) {
continue;
}
particle.bubble.inRange = true;
const divs = bubble.divs, divBubble = (0, engine_1.divMode)(divs, elem);
if (!particle.bubble.div || particle.bubble.div !== elem) {
this.clear(particle, delta, true);
particle.bubble.div = elem;
}
this._hoverBubbleSize(particle, 1, divBubble);
this._hoverBubbleOpacity(particle, 1, divBubble);
this._hoverBubbleColor(particle, 1, divBubble);
}
});
};
if (!container.bubble) {

@@ -65,20 +258,17 @@ container.bubble = {};

if (hoverEnabled && (0, engine_1.isInArray)("bubble", hoverMode)) {
this.hoverBubble(delta);
this._hoverBubble();
}
else if (clickEnabled && (0, engine_1.isInArray)("bubble", clickMode)) {
this.clickBubble(delta);
this._clickBubble();
}
else {
(0, engine_1.divModeExecute)("bubble", divs, (selector, div) => this.singleSelectorHover(delta, selector, div));
(0, engine_1.divModeExecute)("bubble", divs, (selector, div) => this._singleSelectorHover(delta, selector, div));
}
}
isEnabled(particle) {
var _a;
const container = this.container, options = container.actualOptions, mouse = container.interactivity.mouse, events = ((_a = particle === null || particle === void 0 ? void 0 : particle.interactivity) !== null && _a !== void 0 ? _a : options.interactivity).events, divs = events.onDiv, divBubble = (0, engine_1.isDivModeEnabled)("bubble", divs);
if (!(divBubble || (events.onHover.enable && mouse.position) || (events.onClick.enable && mouse.clickPosition))) {
const container = this.container, options = container.actualOptions, mouse = container.interactivity.mouse, events = (particle?.interactivity ?? options.interactivity).events, { onClick, onDiv, onHover } = events, divBubble = (0, engine_1.isDivModeEnabled)("bubble", onDiv);
if (!(divBubble || (onHover.enable && mouse.position) || (onClick.enable && mouse.clickPosition))) {
return false;
}
const hoverMode = events.onHover.mode;
const clickMode = events.onClick.mode;
return (0, engine_1.isInArray)("bubble", hoverMode) || (0, engine_1.isInArray)("bubble", clickMode) || divBubble;
return (0, engine_1.isInArray)("bubble", onHover.mode) || (0, engine_1.isInArray)("bubble", onClick.mode) || divBubble;
}

@@ -90,3 +280,3 @@ loadModeOptions(options, ...sources) {

for (const source of sources) {
options.bubble.load(source === null || source === void 0 ? void 0 : source.bubble);
options.bubble.load(source?.bubble);
}

@@ -97,217 +287,4 @@ }

}
clickBubble(delta) {
var _a, _b;
const container = this.container, options = container.actualOptions, mouseClickPos = container.interactivity.mouse.clickPosition, bubble = options.interactivity.modes.bubble;
if (!bubble || !mouseClickPos) {
return;
}
if (!container.bubble) {
container.bubble = {};
}
const distance = container.retina.bubbleModeDistance;
if (!distance || distance < 0) {
return;
}
const query = container.particles.quadTree.queryCircle(mouseClickPos, distance, (p) => this.isEnabled(p));
for (const particle of query) {
if (!container.bubble.clicking) {
continue;
}
particle.bubble.inRange = !container.bubble.durationEnd;
const pos = particle.getPosition(), distMouse = (0, engine_1.getDistance)(pos, mouseClickPos), timeSpent = (new Date().getTime() - (container.interactivity.mouse.clickTime || 0)) / 1000;
if (timeSpent > bubble.duration) {
container.bubble.durationEnd = true;
}
if (timeSpent > bubble.duration * 2) {
container.bubble.clicking = false;
container.bubble.durationEnd = false;
}
const sizeData = {
bubbleObj: {
optValue: container.retina.bubbleModeSize,
value: particle.bubble.radius,
},
particlesObj: {
optValue: (0, engine_1.getRangeMax)(particle.options.size.value) * container.retina.pixelRatio,
value: particle.size.value,
},
type: "size",
};
this.process(particle, distMouse, timeSpent, sizeData);
const opacityData = {
bubbleObj: {
optValue: bubble.opacity,
value: particle.bubble.opacity,
},
particlesObj: {
optValue: (0, engine_1.getRangeMax)(particle.options.opacity.value),
value: (_b = (_a = particle.opacity) === null || _a === void 0 ? void 0 : _a.value) !== null && _b !== void 0 ? _b : 1,
},
type: "opacity",
};
this.process(particle, distMouse, timeSpent, opacityData);
if (!container.bubble.durationEnd) {
if (distMouse <= distance) {
this.hoverBubbleColor(particle, distMouse);
}
else {
delete particle.bubble.color;
}
}
else {
delete particle.bubble.color;
}
}
}
hoverBubble(delta) {
const container = this.container, mousePos = container.interactivity.mouse.position, distance = container.retina.bubbleModeDistance;
if (!distance || distance < 0 || mousePos === undefined) {
return;
}
const query = container.particles.quadTree.queryCircle(mousePos, distance, (p) => this.isEnabled(p));
for (const particle of query) {
particle.bubble.inRange = true;
const pos = particle.getPosition(), pointDistance = (0, engine_1.getDistance)(pos, mousePos), ratio = 1 - pointDistance / distance;
if (pointDistance <= distance) {
if (ratio >= 0 && container.interactivity.status === engine_1.mouseMoveEvent) {
this.hoverBubbleSize(particle, ratio);
this.hoverBubbleOpacity(particle, ratio);
this.hoverBubbleColor(particle, ratio);
}
}
else {
this.reset(particle);
}
if (container.interactivity.status === engine_1.mouseLeaveEvent) {
this.reset(particle);
}
}
}
hoverBubbleColor(particle, ratio, divBubble) {
const options = this.container.actualOptions;
const bubbleOptions = divBubble !== null && divBubble !== void 0 ? divBubble : options.interactivity.modes.bubble;
if (!bubbleOptions) {
return;
}
if (!particle.bubble.finalColor) {
const modeColor = bubbleOptions.color;
if (!modeColor) {
return;
}
const bubbleColor = (0, engine_1.itemFromSingleOrMultiple)(modeColor);
particle.bubble.finalColor = (0, engine_1.rangeColorToHsl)(bubbleColor);
}
if (!particle.bubble.finalColor) {
return;
}
if (bubbleOptions.mix) {
particle.bubble.color = undefined;
const pColor = particle.getFillColor();
particle.bubble.color = pColor
? (0, engine_1.rgbToHsl)((0, engine_1.colorMix)(pColor, particle.bubble.finalColor, 1 - ratio, ratio))
: particle.bubble.finalColor;
}
else {
particle.bubble.color = particle.bubble.finalColor;
}
}
hoverBubbleOpacity(particle, ratio, divBubble) {
var _a, _b, _c, _d;
const container = this.container, options = container.actualOptions, modeOpacity = (_a = divBubble === null || divBubble === void 0 ? void 0 : divBubble.opacity) !== null && _a !== void 0 ? _a : (_b = options.interactivity.modes.bubble) === null || _b === void 0 ? void 0 : _b.opacity;
if (!modeOpacity) {
return;
}
const optOpacity = particle.options.opacity.value;
const pOpacity = (_d = (_c = particle.opacity) === null || _c === void 0 ? void 0 : _c.value) !== null && _d !== void 0 ? _d : 1;
const opacity = calculateBubbleValue(pOpacity, modeOpacity, (0, engine_1.getRangeMax)(optOpacity), ratio);
if (opacity !== undefined) {
particle.bubble.opacity = opacity;
}
}
hoverBubbleSize(particle, ratio, divBubble) {
const container = this.container, modeSize = (divBubble === null || divBubble === void 0 ? void 0 : divBubble.size) ? divBubble.size * container.retina.pixelRatio : container.retina.bubbleModeSize;
if (modeSize === undefined) {
return;
}
const optSize = (0, engine_1.getRangeMax)(particle.options.size.value) * container.retina.pixelRatio;
const pSize = particle.size.value;
const size = calculateBubbleValue(pSize, modeSize, optSize, ratio);
if (size !== undefined) {
particle.bubble.radius = size;
}
}
process(particle, distMouse, timeSpent, data) {
const container = this.container, bubbleParam = data.bubbleObj.optValue, options = container.actualOptions, bubble = options.interactivity.modes.bubble;
if (!bubble || bubbleParam === undefined) {
return;
}
const bubbleDuration = bubble.duration, bubbleDistance = container.retina.bubbleModeDistance, particlesParam = data.particlesObj.optValue, pObjBubble = data.bubbleObj.value, pObj = data.particlesObj.value || 0, type = data.type;
if (!bubbleDistance || bubbleDistance < 0 || bubbleParam === particlesParam) {
return;
}
if (!container.bubble) {
container.bubble = {};
}
if (!container.bubble.durationEnd) {
if (distMouse <= bubbleDistance) {
const obj = pObjBubble !== null && pObjBubble !== void 0 ? pObjBubble : pObj;
if (obj !== bubbleParam) {
const value = pObj - (timeSpent * (pObj - bubbleParam)) / bubbleDuration;
if (type === "size") {
particle.bubble.radius = value;
}
if (type === "opacity") {
particle.bubble.opacity = value;
}
}
}
else {
if (type === "size") {
delete particle.bubble.radius;
}
if (type === "opacity") {
delete particle.bubble.opacity;
}
}
}
else if (pObjBubble) {
if (type === "size") {
delete particle.bubble.radius;
}
if (type === "opacity") {
delete particle.bubble.opacity;
}
}
}
singleSelectorHover(delta, selector, div) {
const container = this.container, selectors = document.querySelectorAll(selector), bubble = container.actualOptions.interactivity.modes.bubble;
if (!bubble || !selectors.length) {
return;
}
selectors.forEach((item) => {
const elem = item, pxRatio = container.retina.pixelRatio, pos = {
x: (elem.offsetLeft + elem.offsetWidth / 2) * pxRatio,
y: (elem.offsetTop + elem.offsetHeight / 2) * pxRatio,
}, repulseRadius = (elem.offsetWidth / 2) * pxRatio, area = div.type === "circle"
? new engine_1.Circle(pos.x, pos.y, repulseRadius)
: new engine_1.Rectangle(elem.offsetLeft * pxRatio, elem.offsetTop * pxRatio, elem.offsetWidth * pxRatio, elem.offsetHeight * pxRatio), query = container.particles.quadTree.query(area, (p) => this.isEnabled(p));
for (const particle of query) {
if (!area.contains(particle.getPosition())) {
continue;
}
particle.bubble.inRange = true;
const divs = bubble.divs;
const divBubble = (0, engine_1.divMode)(divs, elem);
if (!particle.bubble.div || particle.bubble.div !== elem) {
this.clear(particle, delta, true);
particle.bubble.div = elem;
}
this.hoverBubbleSize(particle, 1, divBubble);
this.hoverBubbleOpacity(particle, 1, divBubble);
this.hoverBubbleColor(particle, 1, divBubble);
}
});
}
}
exports.Bubbler = Bubbler;
});

@@ -28,4 +28,4 @@ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {

const Bubbler_1 = require("./Bubbler");
async function loadExternalBubbleInteraction(engine) {
await engine.addInteractor("externalBubble", (container) => new Bubbler_1.Bubbler(container));
async function loadExternalBubbleInteraction(engine, refresh = true) {
await engine.addInteractor("externalBubble", (container) => new Bubbler_1.Bubbler(container), refresh);
}

@@ -32,0 +32,0 @@ exports.loadExternalBubbleInteraction = loadExternalBubbleInteraction;

@@ -7,3 +7,3 @@ (function (factory) {

else if (typeof define === "function" && define.amd) {
define(["require", "exports", "./BubbleBase", "./BubbleDiv", "@tsparticles/engine"], factory);
define(["require", "exports", "@tsparticles/engine", "./BubbleBase", "./BubbleDiv"], factory);
}

@@ -14,5 +14,5 @@ })(function (require, exports) {

exports.Bubble = void 0;
const engine_1 = require("@tsparticles/engine");
const BubbleBase_1 = require("./BubbleBase");
const BubbleDiv_1 = require("./BubbleDiv");
const engine_1 = require("@tsparticles/engine");
class Bubble extends BubbleBase_1.BubbleBase {

@@ -19,0 +19,0 @@ load(data) {

@@ -37,3 +37,3 @@ (function (factory) {

if (data.color !== undefined) {
const sourceColor = this.color instanceof Array ? undefined : this.color;
const sourceColor = (0, engine_1.isArray)(this.color) ? undefined : this.color;
this.color = (0, engine_1.executeOnSingleOrMultiple)(data.color, (color) => {

@@ -40,0 +40,0 @@ return engine_1.OptionsColor.create(sourceColor, color);

@@ -7,3 +7,3 @@ (function (factory) {

else if (typeof define === "function" && define.amd) {
define(["require", "exports", "./BubbleBase", "@tsparticles/engine"], factory);
define(["require", "exports", "./BubbleBase"], factory);
}

@@ -15,3 +15,2 @@ })(function (require, exports) {

const BubbleBase_1 = require("./BubbleBase");
const engine_1 = require("@tsparticles/engine");
class BubbleDiv extends BubbleBase_1.BubbleBase {

@@ -22,8 +21,2 @@ constructor() {

}
get ids() {
return (0, engine_1.executeOnSingleOrMultiple)(this.selectors, (t) => t.replace("#", ""));
}
set ids(value) {
this.selectors = (0, engine_1.executeOnSingleOrMultiple)(value, (t) => `#${t}`);
}
load(data) {

@@ -34,5 +27,2 @@ super.load(data);

}
if (data.ids !== undefined) {
this.ids = data.ids;
}
if (data.selectors !== undefined) {

@@ -39,0 +29,0 @@ this.selectors = data.selectors;

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc