@tsparticles/interaction-external-bounce
Version:
tsParticles bounce external interaction
209 lines (201 loc) • 12.5 kB
JavaScript
(function(g){g.__tsParticlesInternals=g.__tsParticlesInternals||{};g.__tsParticlesInternals.bundles=g.__tsParticlesInternals.bundles||{};g.__tsParticlesInternals.effects=g.__tsParticlesInternals.effects||{};g.__tsParticlesInternals.engine=g.__tsParticlesInternals.engine||{};g.__tsParticlesInternals.interactions=g.__tsParticlesInternals.interactions||{};g.__tsParticlesInternals.palettes=g.__tsParticlesInternals.palettes||{};g.__tsParticlesInternals.paths=g.__tsParticlesInternals.paths||{};g.__tsParticlesInternals.plugins=g.__tsParticlesInternals.plugins||{};g.__tsParticlesInternals.plugins=g.__tsParticlesInternals.plugins||{};g.__tsParticlesInternals.plugins.emittersShapes=g.__tsParticlesInternals.plugins.emittersShapes||{};g.__tsParticlesInternals.presets=g.__tsParticlesInternals.presets||{};g.__tsParticlesInternals.shapes=g.__tsParticlesInternals.shapes||{};g.__tsParticlesInternals.updaters=g.__tsParticlesInternals.updaters||{};g.__tsParticlesInternals.utils=g.__tsParticlesInternals.utils||{};g.__tsParticlesInternals.canvas=g.__tsParticlesInternals.canvas||{};g.__tsParticlesInternals.canvas=g.__tsParticlesInternals.canvas||{};g.__tsParticlesInternals.canvas.utils=g.__tsParticlesInternals.canvas.utils||{};g.__tsParticlesInternals.path=g.__tsParticlesInternals.path||{};g.__tsParticlesInternals.path=g.__tsParticlesInternals.path||{};g.__tsParticlesInternals.path.utils=g.__tsParticlesInternals.path.utils||{};var __tsProxyFactory=typeof Proxy!=="undefined"?function(obj){return new Proxy(obj,{get:function(target,key){if(!(key in target)){target[key]={};}return target[key];}});}:function(obj){return obj;};g.__tsParticlesInternals.bundles=__tsProxyFactory(g.__tsParticlesInternals.bundles);g.__tsParticlesInternals.effects=__tsProxyFactory(g.__tsParticlesInternals.effects);g.__tsParticlesInternals.interactions=__tsProxyFactory(g.__tsParticlesInternals.interactions);g.__tsParticlesInternals.palettes=__tsProxyFactory(g.__tsParticlesInternals.palettes);g.__tsParticlesInternals.paths=__tsProxyFactory(g.__tsParticlesInternals.paths);g.__tsParticlesInternals.plugins=__tsProxyFactory(g.__tsParticlesInternals.plugins);g.__tsParticlesInternals.plugins.emittersShapes=__tsProxyFactory(g.__tsParticlesInternals.plugins.emittersShapes);g.__tsParticlesInternals.presets=__tsProxyFactory(g.__tsParticlesInternals.presets);g.__tsParticlesInternals.shapes=__tsProxyFactory(g.__tsParticlesInternals.shapes);g.__tsParticlesInternals.updaters=__tsProxyFactory(g.__tsParticlesInternals.updaters);g.__tsParticlesInternals.utils=__tsProxyFactory(g.__tsParticlesInternals.utils);g.__tsParticlesInternals.canvas=__tsProxyFactory(g.__tsParticlesInternals.canvas);g.__tsParticlesInternals.path=__tsProxyFactory(g.__tsParticlesInternals.path);g.tsparticlesInternalExports=g.tsparticlesInternalExports||{};})(typeof globalThis!=="undefined"?globalThis:typeof window!=="undefined"?window:this);
/* External Interaction v4.3.2 */
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@tsparticles/plugin-interactivity'), require('@tsparticles/engine')) :
typeof define === 'function' && define.amd ? define(['exports', '@tsparticles/plugin-interactivity', '@tsparticles/engine'], factory) :
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory((global.__tsParticlesInternals = global.__tsParticlesInternals || {}, global.__tsParticlesInternals.interactions = global.__tsParticlesInternals.interactions || {}, global.__tsParticlesInternals.interactions.externalBounce = global.__tsParticlesInternals.interactions.externalBounce || {}), global.__tsParticlesInternals.plugins.interactivity, global.__tsParticlesInternals.engine));
})(this, (function (exports, pluginInteractivity, engine) { 'use strict';
const halfPI = Math.PI * engine.half, toleranceFactor = 10;
function processBounce(container, position, radius, area, enabledCb) {
const query = container.particles.grid.query(area, enabledCb);
for (const particle of query) {
if (area instanceof engine.Circle) {
engine.circleBounce(engine.circleBounceDataFromParticle(particle), {
position,
radius,
mass: radius ** engine.squareExp * halfPI,
velocity: engine.Vector.origin,
factor: engine.Vector.origin,
});
}
else if (area instanceof engine.Rectangle) {
rectBounce(particle, engine.calculateBounds(position, radius));
}
}
}
function singleSelectorBounce(container, selector, div, bounceCb) {
const query = engine.safeDocument().querySelectorAll(selector);
if (!query.length) {
return;
}
query.forEach(item => {
const elem = item, pxRatio = container.retina.pixelRatio, pos = {
x: (elem.offsetLeft + elem.offsetWidth * engine.half) * pxRatio,
y: (elem.offsetTop + elem.offsetHeight * engine.half) * pxRatio,
}, radius = elem.offsetWidth * engine.half * pxRatio, tolerance = toleranceFactor * pxRatio, area = div.type === pluginInteractivity.DivType.circle
? new engine.Circle(pos.x, pos.y, radius + tolerance)
: new engine.Rectangle(elem.offsetLeft * pxRatio - tolerance, elem.offsetTop * pxRatio - tolerance, elem.offsetWidth * pxRatio + tolerance * engine.double, elem.offsetHeight * pxRatio + tolerance * engine.double);
bounceCb(pos, radius, area);
});
}
function divBounce(container, divs, bounceMode, enabledCb) {
pluginInteractivity.divModeExecute(bounceMode, divs, (selector, div) => {
singleSelectorBounce(container, selector, div, (pos, radius, area) => {
processBounce(container, pos, radius, area, enabledCb);
});
});
}
function mouseBounce(container, interactivityData, enabledCb) {
const pxRatio = container.retina.pixelRatio, tolerance = toleranceFactor * pxRatio, mousePos = interactivityData.mouse.position, radius = container.retina.bounceModeDistance;
if (!radius || radius < engine.minRadius || !mousePos) {
return;
}
processBounce(container, mousePos, radius, new engine.Circle(mousePos.x, mousePos.y, radius + tolerance), enabledCb);
}
function rectSideBounce(data) {
const res = { bounced: false }, { pSide, pOtherSide, rectSide, rectOtherSide, velocity, factor } = data;
if (pOtherSide.min < rectOtherSide.min ||
pOtherSide.min > rectOtherSide.max ||
pOtherSide.max < rectOtherSide.min ||
pOtherSide.max > rectOtherSide.max) {
return res;
}
if ((pSide.max >= rectSide.min && pSide.max <= (rectSide.max + rectSide.min) * engine.half && velocity > engine.minVelocity) ||
(pSide.min <= rectSide.max && pSide.min > (rectSide.max + rectSide.min) * engine.half && velocity < engine.minVelocity)) {
res.velocity = velocity * -factor;
res.bounced = true;
}
return res;
}
function rectBounce(particle, divBounds) {
const pPos = particle.getPosition(), size = particle.getRadius(), bounds = engine.calculateBounds(pPos, size), bounceOptions = particle.options.bounce, resH = rectSideBounce({
pSide: {
min: bounds.left,
max: bounds.right,
},
pOtherSide: {
min: bounds.top,
max: bounds.bottom,
},
rectSide: {
min: divBounds.left,
max: divBounds.right,
},
rectOtherSide: {
min: divBounds.top,
max: divBounds.bottom,
},
velocity: particle.velocity.x,
factor: engine.getRangeValue(bounceOptions.horizontal.value),
});
if (resH.bounced) {
if (resH.velocity !== undefined) {
particle.velocity.x = resH.velocity;
}
if (resH.position !== undefined) {
particle.position.x = resH.position;
}
}
const resV = rectSideBounce({
pSide: {
min: bounds.top,
max: bounds.bottom,
},
pOtherSide: {
min: bounds.left,
max: bounds.right,
},
rectSide: {
min: divBounds.top,
max: divBounds.bottom,
},
rectOtherSide: {
min: divBounds.left,
max: divBounds.right,
},
velocity: particle.velocity.y,
factor: engine.getRangeValue(bounceOptions.vertical.value),
});
if (resV.bounced) {
if (resV.velocity !== undefined) {
particle.velocity.y = resV.velocity;
}
if (resV.position !== undefined) {
particle.position.y = resV.position;
}
}
}
class Bounce {
distance = 200;
load(data) {
if (engine.isNull(data)) {
return;
}
engine.loadProperty(this, "distance", data.distance);
}
}
const bounceMode = "bounce";
class Bouncer extends pluginInteractivity.ExternalInteractorBase {
#maxDistance;
constructor(container) {
super(container);
this.#maxDistance = 0;
}
get maxDistance() {
return this.#maxDistance;
}
clear() {
}
init() {
const container = this.container, bounce = container.actualOptions.interactivity?.modes.bounce;
if (!bounce) {
return;
}
this.#maxDistance = bounce.distance;
container.retina.bounceModeDistance = bounce.distance * container.retina.pixelRatio;
}
interact(interactivityData) {
const container = this.container, options = container.actualOptions, events = options.interactivity?.events, mouseMoveStatus = interactivityData.status === pluginInteractivity.mouseMoveEvent;
if (!events) {
return;
}
const hoverEnabled = events.onHover.enable, hoverMode = events.onHover.mode, divs = events.onDiv;
if (mouseMoveStatus && hoverEnabled && engine.isInArray(bounceMode, hoverMode)) {
mouseBounce(this.container, interactivityData, p => this.isEnabled(interactivityData, p));
}
else {
divBounce(this.container, divs, bounceMode, p => this.isEnabled(interactivityData, p));
}
}
isEnabled(interactivityData, particle) {
const container = this.container, options = container.actualOptions, mouse = interactivityData.mouse, events = (particle?.interactivity ?? options.interactivity)?.events;
if (!events) {
return false;
}
const divs = events.onDiv;
return ((!!mouse.position && events.onHover.enable && engine.isInArray(bounceMode, events.onHover.mode)) ||
pluginInteractivity.isDivModeEnabled(bounceMode, divs));
}
loadModeOptions(options, ...sources) {
engine.loadOptionProperty(options, "bounce", Bounce, ...sources);
}
reset() {
}
}
async function loadExternalBounceInteraction(engine) {
engine.checkVersion("4.3.2");
await engine.pluginManager.register((e) => {
pluginInteractivity.ensureInteractivityPluginLoaded(e);
e.pluginManager.addInteractor?.("externalBounce", container => {
return Promise.resolve(new Bouncer(container));
});
});
}
const globalObject = globalThis;
globalObject.__tsParticlesInternals = globalObject.__tsParticlesInternals ?? {};
globalObject.loadExternalBounceInteraction = loadExternalBounceInteraction;
exports.Bounce = Bounce;
exports.loadExternalBounceInteraction = loadExternalBounceInteraction;
}));
Object.assign(globalThis.window || globalThis, { loadExternalBounceInteraction: (globalThis.__tsParticlesInternals.interactions.externalBounce || {}).loadExternalBounceInteraction });
delete (globalThis.window || globalThis).tsparticlesInternalExports;