@tsparticles/interaction-external-bubble
Advanced tools
Comparing version 3.0.0-alpha.1 to 3.0.0-beta.0
@@ -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
72
77
391123
2290