tsparticles
Version:
Easily create highly customizable particle, confetti and fireworks animations and use them as animated backgrounds for your website. Ready to use components available also for React, Vue.js (2.x and 3.x), Angular, Svelte, jQuery, Preact, Riot.js, Inferno.
1,247 lines (1,240 loc) • 190 kB
JavaScript
(function webpackUniversalModuleDefinition(root, factory) {
if (typeof exports === "object" && typeof module === "object") module.exports = factory(); else if (typeof define === "function" && define.amd) define([], factory); else {
var a = factory();
for (var i in a) (typeof exports === "object" ? exports : root)[i] = a[i];
}
})(window, (function() {
return function() {
"use strict";
var __webpack_require__ = {};
!function() {
__webpack_require__.d = function(exports, definition) {
for (var key in definition) {
if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
Object.defineProperty(exports, key, {
enumerable: true,
get: definition[key]
});
}
}
};
}();
!function() {
__webpack_require__.o = function(obj, prop) {
return Object.prototype.hasOwnProperty.call(obj, prop);
};
}();
!function() {
__webpack_require__.r = function(exports) {
if (typeof Symbol !== "undefined" && Symbol.toStringTag) {
Object.defineProperty(exports, Symbol.toStringTag, {
value: "Module"
});
}
Object.defineProperty(exports, "__esModule", {
value: true
});
};
}();
var __webpack_exports__ = {};
__webpack_require__.r(__webpack_exports__);
__webpack_require__.d(__webpack_exports__, {
loadAngleUpdater: function() {
return loadAngleUpdater;
}
});
class Circle_Circle extends(null && Range){
constructor(x, y, radius) {
super(x, y);
this.radius = radius;
}
contains(point) {
return getDistance(point, this.position) <= this.radius;
}
intersects(range) {
const rect = range;
const circle = range;
const pos1 = this.position;
const pos2 = range.position;
const xDist = Math.abs(pos2.x - pos1.x);
const yDist = Math.abs(pos2.y - pos1.y);
const r = this.radius;
if (circle.radius !== undefined) {
const rSum = r + circle.radius;
const dist = Math.sqrt(xDist * xDist + yDist + yDist);
return rSum > dist;
} else if (rect.size !== undefined) {
const w = rect.size.width;
const h = rect.size.height;
const edges = Math.pow(xDist - w, 2) + Math.pow(yDist - h, 2);
if (xDist > r + w || yDist > r + h) {
return false;
}
if (xDist <= w || yDist <= h) {
return true;
}
return edges <= r * r;
}
return false;
}
}
class CircleWarp_CircleWarp extends(null && Circle){
constructor(x, y, radius, canvasSize) {
super(x, y, radius);
this.canvasSize = canvasSize;
this.canvasSize = {
height: canvasSize.height,
width: canvasSize.width
};
}
contains(point) {
if (super.contains(point)) {
return true;
}
const posNE = {
x: point.x - this.canvasSize.width,
y: point.y
};
if (super.contains(posNE)) {
return true;
}
const posSE = {
x: point.x - this.canvasSize.width,
y: point.y - this.canvasSize.height
};
if (super.contains(posSE)) {
return true;
}
const posSW = {
x: point.x,
y: point.y - this.canvasSize.height
};
return super.contains(posSW);
}
intersects(range) {
if (super.intersects(range)) {
return true;
}
const rect = range;
const circle = range;
const newPos = {
x: range.position.x - this.canvasSize.width,
y: range.position.y - this.canvasSize.height
};
if (circle.radius !== undefined) {
const biggerCircle = new Circle(newPos.x, newPos.y, circle.radius * 2);
return super.intersects(biggerCircle);
} else if (rect.size !== undefined) {
const rectSW = new Rectangle(newPos.x, newPos.y, rect.size.width * 2, rect.size.height * 2);
return super.intersects(rectSW);
}
return false;
}
}
class Constants_Constants {}
Constants_Constants.generatedAttribute = "generated";
Constants_Constants.randomColorValue = "random";
Constants_Constants.midColorValue = "mid";
Constants_Constants.touchEndEvent = "touchend";
Constants_Constants.mouseDownEvent = "mousedown";
Constants_Constants.mouseUpEvent = "mouseup";
Constants_Constants.mouseMoveEvent = "mousemove";
Constants_Constants.touchStartEvent = "touchstart";
Constants_Constants.touchMoveEvent = "touchmove";
Constants_Constants.mouseLeaveEvent = "mouseleave";
Constants_Constants.mouseOutEvent = "mouseout";
Constants_Constants.touchCancelEvent = "touchcancel";
Constants_Constants.resizeEvent = "resize";
Constants_Constants.visibilityChangeEvent = "visibilitychange";
Constants_Constants.noPolygonDataLoaded = "No polygon data loaded.";
Constants_Constants.noPolygonFound = "No polygon found, you need to specify SVG url in config.";
function manageListener(element, event, handler, add, options) {
if (add) {
let addOptions = {
passive: true
};
if (typeof options === "boolean") {
addOptions.capture = options;
} else if (options !== undefined) {
addOptions = options;
}
element.addEventListener(event, handler, addOptions);
} else {
const removeOptions = options;
element.removeEventListener(event, handler, removeOptions);
}
}
class EventListeners_EventListeners {
constructor(container) {
this.container = container;
this.canPush = true;
this.mouseMoveHandler = e => this.mouseTouchMove(e);
this.touchStartHandler = e => this.mouseTouchMove(e);
this.touchMoveHandler = e => this.mouseTouchMove(e);
this.touchEndHandler = () => this.mouseTouchFinish();
this.mouseLeaveHandler = () => this.mouseTouchFinish();
this.touchCancelHandler = () => this.mouseTouchFinish();
this.touchEndClickHandler = e => this.mouseTouchClick(e);
this.mouseUpHandler = e => this.mouseTouchClick(e);
this.mouseDownHandler = () => this.mouseDown();
this.visibilityChangeHandler = () => this.handleVisibilityChange();
this.themeChangeHandler = e => this.handleThemeChange(e);
this.oldThemeChangeHandler = e => this.handleThemeChange(e);
this.resizeHandler = () => this.handleWindowResize();
}
addListeners() {
this.manageListeners(true);
}
removeListeners() {
this.manageListeners(false);
}
manageListeners(add) {
var _a;
const container = this.container;
const options = container.actualOptions;
const detectType = options.interactivity.detectsOn;
let mouseLeaveEvent = Constants.mouseLeaveEvent;
if (detectType === "window") {
container.interactivity.element = window;
mouseLeaveEvent = Constants.mouseOutEvent;
} else if (detectType === "parent" && container.canvas.element) {
const canvasEl = container.canvas.element;
container.interactivity.element = (_a = canvasEl.parentElement) !== null && _a !== void 0 ? _a : canvasEl.parentNode;
} else {
container.interactivity.element = container.canvas.element;
}
const mediaMatch = !isSsr() && typeof matchMedia !== "undefined" && matchMedia("(prefers-color-scheme: dark)");
if (mediaMatch) {
if (mediaMatch.addEventListener !== undefined) {
manageListener(mediaMatch, "change", this.themeChangeHandler, add);
} else if (mediaMatch.addListener !== undefined) {
if (add) {
mediaMatch.addListener(this.oldThemeChangeHandler);
} else {
mediaMatch.removeListener(this.oldThemeChangeHandler);
}
}
}
const interactivityEl = container.interactivity.element;
if (!interactivityEl) {
return;
}
const html = interactivityEl;
if (options.interactivity.events.onHover.enable || options.interactivity.events.onClick.enable) {
manageListener(interactivityEl, Constants.mouseMoveEvent, this.mouseMoveHandler, add);
manageListener(interactivityEl, Constants.touchStartEvent, this.touchStartHandler, add);
manageListener(interactivityEl, Constants.touchMoveEvent, this.touchMoveHandler, add);
if (!options.interactivity.events.onClick.enable) {
manageListener(interactivityEl, Constants.touchEndEvent, this.touchEndHandler, add);
} else {
manageListener(interactivityEl, Constants.touchEndEvent, this.touchEndClickHandler, add);
manageListener(interactivityEl, Constants.mouseUpEvent, this.mouseUpHandler, add);
manageListener(interactivityEl, Constants.mouseDownEvent, this.mouseDownHandler, add);
}
manageListener(interactivityEl, mouseLeaveEvent, this.mouseLeaveHandler, add);
manageListener(interactivityEl, Constants.touchCancelEvent, this.touchCancelHandler, add);
}
if (container.canvas.element) {
container.canvas.element.style.pointerEvents = html === container.canvas.element ? "initial" : "none";
}
if (options.interactivity.events.resize) {
if (typeof ResizeObserver !== "undefined") {
if (this.resizeObserver && !add) {
if (container.canvas.element) {
this.resizeObserver.unobserve(container.canvas.element);
}
this.resizeObserver.disconnect();
delete this.resizeObserver;
} else if (!this.resizeObserver && add && container.canvas.element) {
this.resizeObserver = new ResizeObserver((entries => {
const entry = entries.find((e => e.target === container.canvas.element));
if (!entry) {
return;
}
this.handleWindowResize();
}));
this.resizeObserver.observe(container.canvas.element);
}
} else {
manageListener(window, Constants.resizeEvent, this.resizeHandler, add);
}
}
if (document) {
manageListener(document, Constants.visibilityChangeEvent, this.visibilityChangeHandler, add, false);
}
}
handleWindowResize() {
if (this.resizeTimeout) {
clearTimeout(this.resizeTimeout);
delete this.resizeTimeout;
}
this.resizeTimeout = setTimeout((async () => {
var _a;
return await ((_a = this.container.canvas) === null || _a === void 0 ? void 0 : _a.windowResize());
}), 500);
}
handleVisibilityChange() {
const container = this.container;
const options = container.actualOptions;
this.mouseTouchFinish();
if (!options.pauseOnBlur) {
return;
}
if (document === null || document === void 0 ? void 0 : document.hidden) {
container.pageHidden = true;
container.pause();
} else {
container.pageHidden = false;
if (container.getAnimationStatus()) {
container.play(true);
} else {
container.draw(true);
}
}
}
mouseDown() {
const interactivity = this.container.interactivity;
if (interactivity) {
const mouse = interactivity.mouse;
mouse.clicking = true;
mouse.downPosition = mouse.position;
}
}
mouseTouchMove(e) {
var _a, _b, _c, _d, _e, _f, _g;
const container = this.container;
const options = container.actualOptions;
if (((_a = container.interactivity) === null || _a === void 0 ? void 0 : _a.element) === undefined) {
return;
}
container.interactivity.mouse.inside = true;
let pos;
const canvas = container.canvas.element;
if (e.type.startsWith("mouse")) {
this.canPush = true;
const mouseEvent = e;
if (container.interactivity.element === window) {
if (canvas) {
const clientRect = canvas.getBoundingClientRect();
pos = {
x: mouseEvent.clientX - clientRect.left,
y: mouseEvent.clientY - clientRect.top
};
}
} else if (options.interactivity.detectsOn === "parent") {
const source = mouseEvent.target;
const target = mouseEvent.currentTarget;
const canvasEl = container.canvas.element;
if (source && target && canvasEl) {
const sourceRect = source.getBoundingClientRect();
const targetRect = target.getBoundingClientRect();
const canvasRect = canvasEl.getBoundingClientRect();
pos = {
x: mouseEvent.offsetX + 2 * sourceRect.left - (targetRect.left + canvasRect.left),
y: mouseEvent.offsetY + 2 * sourceRect.top - (targetRect.top + canvasRect.top)
};
} else {
pos = {
x: (_b = mouseEvent.offsetX) !== null && _b !== void 0 ? _b : mouseEvent.clientX,
y: (_c = mouseEvent.offsetY) !== null && _c !== void 0 ? _c : mouseEvent.clientY
};
}
} else {
if (mouseEvent.target === container.canvas.element) {
pos = {
x: (_d = mouseEvent.offsetX) !== null && _d !== void 0 ? _d : mouseEvent.clientX,
y: (_e = mouseEvent.offsetY) !== null && _e !== void 0 ? _e : mouseEvent.clientY
};
}
}
} else {
this.canPush = e.type !== "touchmove";
const touchEvent = e;
const lastTouch = touchEvent.touches[touchEvent.touches.length - 1];
const canvasRect = canvas === null || canvas === void 0 ? void 0 : canvas.getBoundingClientRect();
pos = {
x: lastTouch.clientX - ((_f = canvasRect === null || canvasRect === void 0 ? void 0 : canvasRect.left) !== null && _f !== void 0 ? _f : 0),
y: lastTouch.clientY - ((_g = canvasRect === null || canvasRect === void 0 ? void 0 : canvasRect.top) !== null && _g !== void 0 ? _g : 0)
};
}
const pxRatio = container.retina.pixelRatio;
if (pos) {
pos.x *= pxRatio;
pos.y *= pxRatio;
}
container.interactivity.mouse.position = pos;
container.interactivity.status = Constants.mouseMoveEvent;
}
mouseTouchFinish() {
const interactivity = this.container.interactivity;
if (interactivity === undefined) {
return;
}
const mouse = interactivity.mouse;
delete mouse.position;
delete mouse.clickPosition;
delete mouse.downPosition;
interactivity.status = Constants.mouseLeaveEvent;
mouse.inside = false;
mouse.clicking = false;
}
mouseTouchClick(e) {
const container = this.container;
const options = container.actualOptions;
const mouse = container.interactivity.mouse;
mouse.inside = true;
let handled = false;
const mousePosition = mouse.position;
if (mousePosition === undefined || !options.interactivity.events.onClick.enable) {
return;
}
for (const [, plugin] of container.plugins) {
if (plugin.clickPositionValid !== undefined) {
handled = plugin.clickPositionValid(mousePosition);
if (handled) {
break;
}
}
}
if (!handled) {
this.doMouseTouchClick(e);
}
mouse.clicking = false;
}
doMouseTouchClick(e) {
const container = this.container;
const options = container.actualOptions;
if (this.canPush) {
const mousePos = container.interactivity.mouse.position;
if (mousePos) {
container.interactivity.mouse.clickPosition = {
x: mousePos.x,
y: mousePos.y
};
} else {
return;
}
container.interactivity.mouse.clickTime = (new Date).getTime();
const onClick = options.interactivity.events.onClick;
if (onClick.mode instanceof Array) {
for (const mode of onClick.mode) {
this.handleClickMode(mode);
}
} else {
this.handleClickMode(onClick.mode);
}
}
if (e.type === "touchend") {
setTimeout((() => this.mouseTouchFinish()), 500);
}
}
handleThemeChange(e) {
const mediaEvent = e;
const themeName = mediaEvent.matches ? this.container.options.defaultDarkTheme : this.container.options.defaultLightTheme;
const theme = this.container.options.themes.find((theme => theme.name === themeName));
if (theme && theme.default.auto) {
this.container.loadTheme(themeName);
}
}
handleClickMode(mode) {
const container = this.container;
const options = container.actualOptions;
const pushNb = options.interactivity.modes.push.quantity;
const removeNb = options.interactivity.modes.remove.quantity;
switch (mode) {
case "push":
{
if (pushNb > 0) {
const pushOptions = options.interactivity.modes.push;
const group = itemFromArray([ undefined, ...pushOptions.groups ]);
const groupOptions = group !== undefined ? container.actualOptions.particles.groups[group] : undefined;
container.particles.push(pushNb, container.interactivity.mouse, groupOptions, group);
}
break;
}
case "remove":
container.particles.removeQuantity(removeNb);
break;
case "bubble":
container.bubble.clicking = true;
break;
case "repulse":
container.repulse.clicking = true;
container.repulse.count = 0;
for (const particle of container.repulse.particles) {
particle.velocity.setTo(particle.initialVelocity);
}
container.repulse.particles = [];
container.repulse.finish = false;
setTimeout((() => {
if (!container.destroyed) {
container.repulse.clicking = false;
}
}), options.interactivity.modes.repulse.duration * 1e3);
break;
case "attract":
container.attract.clicking = true;
container.attract.count = 0;
for (const particle of container.attract.particles) {
particle.velocity.setTo(particle.initialVelocity);
}
container.attract.particles = [];
container.attract.finish = false;
setTimeout((() => {
if (!container.destroyed) {
container.attract.clicking = false;
}
}), options.interactivity.modes.attract.duration * 1e3);
break;
case "pause":
if (container.getAnimationStatus()) {
container.pause();
} else {
container.play();
}
break;
}
for (const [, plugin] of container.plugins) {
if (plugin.handleClickMode) {
plugin.handleClickMode(mode);
}
}
}
}
var __classPrivateFieldSet = undefined && undefined.__classPrivateFieldSet || function(receiver, state, value, kind, f) {
if (kind === "m") throw new TypeError("Private method is not writable");
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
return kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value),
value;
};
var __classPrivateFieldGet = undefined && undefined.__classPrivateFieldGet || function(receiver, state, kind, f) {
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
};
var _InteractionManager_engine;
class InteractionManager_InteractionManager {
constructor(engine, container) {
this.container = container;
_InteractionManager_engine.set(this, void 0);
__classPrivateFieldSet(this, _InteractionManager_engine, engine, "f");
this.externalInteractors = [];
this.particleInteractors = [];
this.init();
}
init() {
const interactors = __classPrivateFieldGet(this, _InteractionManager_engine, "f").plugins.getInteractors(this.container, true);
this.externalInteractors = [];
this.particleInteractors = [];
for (const interactor of interactors) {
switch (interactor.type) {
case 0:
this.externalInteractors.push(interactor);
break;
case 1:
this.particleInteractors.push(interactor);
break;
}
}
}
async externalInteract(delta) {
for (const interactor of this.externalInteractors) {
if (interactor.isEnabled()) {
await interactor.interact(delta);
}
}
}
async particlesInteract(particle, delta) {
for (const interactor of this.externalInteractors) {
interactor.reset(particle);
}
for (const interactor of this.particleInteractors) {
if (interactor.isEnabled(particle)) {
await interactor.interact(particle, delta);
}
}
}
}
_InteractionManager_engine = new WeakMap;
function applyDistance(particle) {
const initialPosition = particle.initialPosition;
const {dx: dx, dy: dy} = getDistances(initialPosition, particle.position);
const dxFixed = Math.abs(dx), dyFixed = Math.abs(dy);
const hDistance = particle.retina.maxDistance.horizontal;
const vDistance = particle.retina.maxDistance.vertical;
if (!hDistance && !vDistance) {
return;
}
if ((hDistance && dxFixed >= hDistance || vDistance && dyFixed >= vDistance) && !particle.misplaced) {
particle.misplaced = !!hDistance && dxFixed > hDistance || !!vDistance && dyFixed > vDistance;
if (hDistance) {
particle.velocity.x = particle.velocity.y / 2 - particle.velocity.x;
}
if (vDistance) {
particle.velocity.y = particle.velocity.x / 2 - particle.velocity.y;
}
} else if ((!hDistance || dxFixed < hDistance) && (!vDistance || dyFixed < vDistance) && particle.misplaced) {
particle.misplaced = false;
} else if (particle.misplaced) {
const pos = particle.position, vel = particle.velocity;
if (hDistance && (pos.x < initialPosition.x && vel.x < 0 || pos.x > initialPosition.x && vel.x > 0)) {
vel.x *= -Math.random();
}
if (vDistance && (pos.y < initialPosition.y && vel.y < 0 || pos.y > initialPosition.y && vel.y > 0)) {
vel.y *= -Math.random();
}
}
}
class ParticlesMover_ParticlesMover {
constructor(container) {
this.container = container;
}
move(particle, delta) {
if (particle.destroyed) {
return;
}
this.moveParticle(particle, delta);
this.moveParallax(particle);
}
moveParticle(particle, delta) {
var _a, _b, _c;
var _d, _e;
const particleOptions = particle.options;
const moveOptions = particleOptions.move;
if (!moveOptions.enable) {
return;
}
const container = this.container, slowFactor = this.getProximitySpeedFactor(particle), baseSpeed = ((_a = (_d = particle.retina).moveSpeed) !== null && _a !== void 0 ? _a : _d.moveSpeed = getRangeValue(moveOptions.speed) * container.retina.pixelRatio) * container.retina.reduceFactor, moveDrift = (_b = (_e = particle.retina).moveDrift) !== null && _b !== void 0 ? _b : _e.moveDrift = getRangeValue(particle.options.move.drift) * container.retina.pixelRatio, maxSize = getRangeMax(particleOptions.size.value) * container.retina.pixelRatio, sizeFactor = moveOptions.size ? particle.getRadius() / maxSize : 1, diffFactor = 2, speedFactor = sizeFactor * slowFactor * (delta.factor || 1) / diffFactor, moveSpeed = baseSpeed * speedFactor;
this.applyPath(particle, delta);
const gravityOptions = particle.gravity;
const gravityFactor = gravityOptions.enable && gravityOptions.inverse ? -1 : 1;
if (gravityOptions.enable && moveSpeed) {
particle.velocity.y += gravityFactor * (gravityOptions.acceleration * delta.factor) / (60 * moveSpeed);
}
if (moveDrift && moveSpeed) {
particle.velocity.x += moveDrift * delta.factor / (60 * moveSpeed);
}
const decay = particle.moveDecay;
if (decay != 1) {
particle.velocity.multTo(decay);
}
const velocity = particle.velocity.mult(moveSpeed);
const maxSpeed = (_c = particle.retina.maxSpeed) !== null && _c !== void 0 ? _c : container.retina.maxSpeed;
if (gravityOptions.enable && maxSpeed > 0 && (!gravityOptions.inverse && velocity.y >= 0 && velocity.y >= maxSpeed || gravityOptions.inverse && velocity.y <= 0 && velocity.y <= -maxSpeed)) {
velocity.y = gravityFactor * maxSpeed;
if (moveSpeed) {
particle.velocity.y = velocity.y / moveSpeed;
}
}
const zIndexOptions = particle.options.zIndex, zVelocityFactor = (1 - particle.zIndexFactor) ** zIndexOptions.velocityRate;
if (moveOptions.spin.enable) {
this.spin(particle, moveSpeed);
} else {
if (zVelocityFactor != 1) {
velocity.multTo(zVelocityFactor);
}
particle.position.addTo(velocity);
if (moveOptions.vibrate) {
particle.position.x += Math.sin(particle.position.x * Math.cos(particle.position.y));
particle.position.y += Math.cos(particle.position.y * Math.sin(particle.position.x));
}
}
applyDistance(particle);
}
spin(particle, moveSpeed) {
const container = this.container;
if (!particle.spin) {
return;
}
const updateFunc = {
x: particle.spin.direction === "clockwise" ? Math.cos : Math.sin,
y: particle.spin.direction === "clockwise" ? Math.sin : Math.cos
};
particle.position.x = particle.spin.center.x + particle.spin.radius * updateFunc.x(particle.spin.angle);
particle.position.y = particle.spin.center.y + particle.spin.radius * updateFunc.y(particle.spin.angle);
particle.spin.radius += particle.spin.acceleration;
const maxCanvasSize = Math.max(container.canvas.size.width, container.canvas.size.height);
if (particle.spin.radius > maxCanvasSize / 2) {
particle.spin.radius = maxCanvasSize / 2;
particle.spin.acceleration *= -1;
} else if (particle.spin.radius < 0) {
particle.spin.radius = 0;
particle.spin.acceleration *= -1;
}
particle.spin.angle += moveSpeed / 100 * (1 - particle.spin.radius / maxCanvasSize);
}
applyPath(particle, delta) {
const particlesOptions = particle.options;
const pathOptions = particlesOptions.move.path;
const pathEnabled = pathOptions.enable;
if (!pathEnabled) {
return;
}
const container = this.container;
if (particle.lastPathTime <= particle.pathDelay) {
particle.lastPathTime += delta.value;
return;
}
const path = container.pathGenerator.generate(particle);
particle.velocity.addTo(path);
if (pathOptions.clamp) {
particle.velocity.x = clamp(particle.velocity.x, -1, 1);
particle.velocity.y = clamp(particle.velocity.y, -1, 1);
}
particle.lastPathTime -= particle.pathDelay;
}
moveParallax(particle) {
const container = this.container;
const options = container.actualOptions;
if (isSsr() || !options.interactivity.events.onHover.parallax.enable) {
return;
}
const parallaxForce = options.interactivity.events.onHover.parallax.force;
const mousePos = container.interactivity.mouse.position;
if (!mousePos) {
return;
}
const canvasCenter = {
x: container.canvas.size.width / 2,
y: container.canvas.size.height / 2
};
const parallaxSmooth = options.interactivity.events.onHover.parallax.smooth;
const factor = particle.getRadius() / parallaxForce;
const tmp = {
x: (mousePos.x - canvasCenter.x) * factor,
y: (mousePos.y - canvasCenter.y) * factor
};
particle.offset.x += (tmp.x - particle.offset.x) / parallaxSmooth;
particle.offset.y += (tmp.y - particle.offset.y) / parallaxSmooth;
}
getProximitySpeedFactor(particle) {
const container = this.container;
const options = container.actualOptions;
const active = isInArray("slow", options.interactivity.events.onHover.mode);
if (!active) {
return 1;
}
const mousePos = this.container.interactivity.mouse.position;
if (!mousePos) {
return 1;
}
const particlePos = particle.getPosition();
const dist = getDistance(mousePos, particlePos);
const radius = container.retina.slowModeRadius;
if (dist > radius) {
return 1;
}
const proximityFactor = dist / radius || 0;
const slowFactor = options.interactivity.modes.slow.factor;
return proximityFactor / slowFactor;
}
}
var Plugins_classPrivateFieldSet = undefined && undefined.__classPrivateFieldSet || function(receiver, state, value, kind, f) {
if (kind === "m") throw new TypeError("Private method is not writable");
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
return kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value),
value;
};
var _Plugins_engine;
class Plugins {
constructor(engine) {
_Plugins_engine.set(this, void 0);
Plugins_classPrivateFieldSet(this, _Plugins_engine, engine, "f");
this.plugins = [];
this.interactorsInitializers = new Map;
this.updatersInitializers = new Map;
this.interactors = new Map;
this.updaters = new Map;
this.presets = new Map;
this.drawers = new Map;
this.pathGenerators = new Map;
}
getPlugin(plugin) {
return this.plugins.find((t => t.id === plugin));
}
addPlugin(plugin) {
if (!this.getPlugin(plugin.id)) {
this.plugins.push(plugin);
}
}
getAvailablePlugins(container) {
const res = new Map;
for (const plugin of this.plugins) {
if (!plugin.needsPlugin(container.actualOptions)) {
continue;
}
res.set(plugin.id, plugin.getPlugin(container));
}
return res;
}
loadOptions(options, sourceOptions) {
for (const plugin of this.plugins) {
plugin.loadOptions(options, sourceOptions);
}
}
getPreset(preset) {
return this.presets.get(preset);
}
addPreset(presetKey, options, override = false) {
if (override || !this.getPreset(presetKey)) {
this.presets.set(presetKey, options);
}
}
addShapeDrawer(type, drawer) {
if (!this.getShapeDrawer(type)) {
this.drawers.set(type, drawer);
}
}
getShapeDrawer(type) {
return this.drawers.get(type);
}
getSupportedShapes() {
return this.drawers.keys();
}
getPathGenerator(type) {
return this.pathGenerators.get(type);
}
addPathGenerator(type, pathGenerator) {
if (!this.getPathGenerator(type)) {
this.pathGenerators.set(type, pathGenerator);
}
}
getInteractors(container, force = false) {
let res = this.interactors.get(container);
if (!res || force) {
res = [ ...this.interactorsInitializers.values() ].map((t => t(container)));
this.interactors.set(container, res);
}
return res;
}
addInteractor(name, initInteractor) {
this.interactorsInitializers.set(name, initInteractor);
}
getUpdaters(container, force = false) {
let res = this.updaters.get(container);
if (!res || force) {
res = [ ...this.updatersInitializers.values() ].map((t => t(container)));
this.updaters.set(container, res);
}
return res;
}
addParticleUpdater(name, initUpdater) {
this.updatersInitializers.set(name, initUpdater);
}
}
_Plugins_engine = new WeakMap;
class QuadTree_QuadTree {
constructor(rectangle, capacity) {
this.rectangle = rectangle;
this.capacity = capacity;
this.points = [];
this.divided = false;
}
subdivide() {
const x = this.rectangle.position.x;
const y = this.rectangle.position.y;
const w = this.rectangle.size.width;
const h = this.rectangle.size.height;
const capacity = this.capacity;
this.northEast = new QuadTree_QuadTree(new Rectangle(x, y, w / 2, h / 2), capacity);
this.northWest = new QuadTree_QuadTree(new Rectangle(x + w / 2, y, w / 2, h / 2), capacity);
this.southEast = new QuadTree_QuadTree(new Rectangle(x, y + h / 2, w / 2, h / 2), capacity);
this.southWest = new QuadTree_QuadTree(new Rectangle(x + w / 2, y + h / 2, w / 2, h / 2), capacity);
this.divided = true;
}
insert(point) {
var _a, _b, _c, _d, _e;
if (!this.rectangle.contains(point.position)) {
return false;
}
if (this.points.length < this.capacity) {
this.points.push(point);
return true;
}
if (!this.divided) {
this.subdivide();
}
return (_e = ((_a = this.northEast) === null || _a === void 0 ? void 0 : _a.insert(point)) || ((_b = this.northWest) === null || _b === void 0 ? void 0 : _b.insert(point)) || ((_c = this.southEast) === null || _c === void 0 ? void 0 : _c.insert(point)) || ((_d = this.southWest) === null || _d === void 0 ? void 0 : _d.insert(point))) !== null && _e !== void 0 ? _e : false;
}
queryCircle(position, radius) {
return this.query(new Circle(position.x, position.y, radius));
}
queryCircleWarp(position, radius, containerOrSize) {
const container = containerOrSize;
const size = containerOrSize;
return this.query(new CircleWarp(position.x, position.y, radius, container.canvas !== undefined ? container.canvas.size : size));
}
queryRectangle(position, size) {
return this.query(new Rectangle(position.x, position.y, size.width, size.height));
}
query(range, found) {
var _a, _b, _c, _d;
const res = found !== null && found !== void 0 ? found : [];
if (!range.intersects(this.rectangle)) {
return [];
} else {
for (const p of this.points) {
if (!range.contains(p.position) && getDistance(range.position, p.position) > p.particle.getRadius()) {
continue;
}
res.push(p.particle);
}
if (this.divided) {
(_a = this.northEast) === null || _a === void 0 ? void 0 : _a.query(range, res);
(_b = this.northWest) === null || _b === void 0 ? void 0 : _b.query(range, res);
(_c = this.southEast) === null || _c === void 0 ? void 0 : _c.query(range, res);
(_d = this.southWest) === null || _d === void 0 ? void 0 : _d.query(range, res);
}
}
return res;
}
}
class Canvas_Canvas {
constructor(container) {
this.container = container;
this.size = {
height: 0,
width: 0
};
this.context = null;
this.generatedCanvas = false;
}
init() {
this.resize();
this.initStyle();
this.initCover();
this.initTrail();
this.initBackground();
this.paint();
}
loadCanvas(canvas) {
var _a;
if (this.generatedCanvas) {
(_a = this.element) === null || _a === void 0 ? void 0 : _a.remove();
}
this.generatedCanvas = canvas.dataset && Constants.generatedAttribute in canvas.dataset ? canvas.dataset[Constants.generatedAttribute] === "true" : this.generatedCanvas;
this.element = canvas;
this.originalStyle = deepExtend({}, this.element.style);
this.size.height = canvas.offsetHeight;
this.size.width = canvas.offsetWidth;
this.context = this.element.getContext("2d");
this.container.retina.init();
this.initBackground();
}
destroy() {
var _a;
if (this.generatedCanvas) {
(_a = this.element) === null || _a === void 0 ? void 0 : _a.remove();
}
this.draw((ctx => {
clear(ctx, this.size);
}));
}
paint() {
const options = this.container.actualOptions;
this.draw((ctx => {
if (options.backgroundMask.enable && options.backgroundMask.cover) {
clear(ctx, this.size);
this.paintBase(this.coverColorStyle);
} else {
this.paintBase();
}
}));
}
clear() {
const options = this.container.actualOptions;
const trail = options.particles.move.trail;
if (options.backgroundMask.enable) {
this.paint();
} else if (trail.enable && trail.length > 0 && this.trailFillColor) {
this.paintBase(getStyleFromRgb(this.trailFillColor, 1 / trail.length));
} else {
this.draw((ctx => {
clear(ctx, this.size);
}));
}
}
async windowResize() {
if (!this.element) {
return;
}
const container = this.container;
this.resize();
const needsRefresh = container.updateActualOptions();
container.particles.setDensity();
for (const [, plugin] of container.plugins) {
if (plugin.resize !== undefined) {
plugin.resize();
}
}
if (needsRefresh) {
await container.refresh();
}
}
resize() {
if (!this.element) {
return;
}
const container = this.container;
const pxRatio = container.retina.pixelRatio;
const size = container.canvas.size;
const oldSize = Object.assign({}, size);
size.width = this.element.offsetWidth * pxRatio;
size.height = this.element.offsetHeight * pxRatio;
this.element.width = size.width;
this.element.height = size.height;
if (this.container.started) {
this.resizeFactor = {
width: size.width / oldSize.width,
height: size.height / oldSize.height
};
}
}
drawConnectLine(p1, p2) {
this.draw((ctx => {
var _a;
const lineStyle = this.lineStyle(p1, p2);
if (!lineStyle) {
return;
}
const pos1 = p1.getPosition();
const pos2 = p2.getPosition();
drawConnectLine(ctx, (_a = p1.retina.linksWidth) !== null && _a !== void 0 ? _a : this.container.retina.linksWidth, lineStyle, pos1, pos2);
}));
}
drawGrabLine(particle, lineColor, opacity, mousePos) {
const container = this.container;
this.draw((ctx => {
var _a;
const beginPos = particle.getPosition();
drawGrabLine(ctx, (_a = particle.retina.linksWidth) !== null && _a !== void 0 ? _a : container.retina.linksWidth, beginPos, mousePos, lineColor, opacity);
}));
}
drawParticle(particle, delta) {
var _a, _b, _c, _d, _e, _f;
if (particle.spawning || particle.destroyed) {
return;
}
const pfColor = particle.getFillColor();
const psColor = (_a = particle.getStrokeColor()) !== null && _a !== void 0 ? _a : pfColor;
if (!pfColor && !psColor) {
return;
}
let [fColor, sColor] = this.getPluginParticleColors(particle);
const pOptions = particle.options;
const twinkle = pOptions.twinkle.particles;
const twinkling = twinkle.enable && Math.random() < twinkle.frequency;
if (!fColor || !sColor) {
const twinkleRgb = colorToHsl(twinkle.color);
if (!fColor) {
fColor = twinkling && twinkleRgb !== undefined ? twinkleRgb : pfColor ? pfColor : undefined;
}
if (!sColor) {
sColor = twinkling && twinkleRgb !== undefined ? twinkleRgb : psColor ? psColor : undefined;
}
}
const options = this.container.actualOptions;
const zIndexOptions = particle.options.zIndex;
const zOpacityFactor = (1 - particle.zIndexFactor) ** zIndexOptions.opacityRate;
const radius = particle.getRadius();
const opacity = twinkling ? getRangeValue(twinkle.opacity) : (_d = (_b = particle.bubble.opacity) !== null && _b !== void 0 ? _b : (_c = particle.opacity) === null || _c === void 0 ? void 0 : _c.value) !== null && _d !== void 0 ? _d : 1;
const strokeOpacity = (_f = (_e = particle.stroke) === null || _e === void 0 ? void 0 : _e.opacity) !== null && _f !== void 0 ? _f : opacity;
const zOpacity = opacity * zOpacityFactor;
const fillColorValue = fColor ? getStyleFromHsl(fColor, zOpacity) : undefined;
if (!fillColorValue && !sColor) {
return;
}
this.draw((ctx => {
const zSizeFactor = (1 - particle.zIndexFactor) ** zIndexOptions.sizeRate;
const zStrokeOpacity = strokeOpacity * zOpacityFactor;
const strokeColorValue = sColor ? getStyleFromHsl(sColor, zStrokeOpacity) : fillColorValue;
if (radius <= 0) {
return;
}
const container = this.container;
for (const updater of container.particles.updaters) {
if (updater.beforeDraw) {
updater.beforeDraw(particle);
}
}
drawParticle(this.container, ctx, particle, delta, fillColorValue, strokeColorValue, options.backgroundMask.enable, options.backgroundMask.composite, radius * zSizeFactor, zOpacity, particle.options.shadow, particle.gradient);
for (const updater of container.particles.updaters) {
if (updater.afterDraw) {
updater.afterDraw(particle);
}
}
}));
}
drawPlugin(plugin, delta) {
this.draw((ctx => {
drawPlugin(ctx, plugin, delta);
}));
}
drawParticlePlugin(plugin, particle, delta) {
this.draw((ctx => {
drawParticlePlugin(ctx, plugin, particle, delta);
}));
}
initBackground() {
const options = this.container.actualOptions;
const background = options.background;
const element = this.element;
const elementStyle = element === null || element === void 0 ? void 0 : element.style;
if (!elementStyle) {
return;
}
if (background.color) {
const color = colorToRgb(background.color);
elementStyle.backgroundColor = color ? getStyleFromRgb(color, background.opacity) : "";
} else {
elementStyle.backgroundColor = "";
}
elementStyle.backgroundImage = background.image || "";
elementStyle.backgroundPosition = background.position || "";
elementStyle.backgroundRepeat = background.repeat || "";
elementStyle.backgroundSize = background.size || "";
}
draw(cb) {
if (!this.context) {
return;
}
return cb(this.context);
}
initCover() {
const options = this.container.actualOptions;
const cover = options.backgroundMask.cover;
const color = cover.color;
const coverRgb = colorToRgb(color);
if (coverRgb) {
const coverColor = {
r: coverRgb.r,
g: coverRgb.g,
b: coverRgb.b,
a: cover.opacity
};
this.coverColorStyle = getStyleFromRgb(coverColor, coverColor.a);
console.log(this.coverColorStyle);
}
}
initTrail() {
const options = this.container.actualOptions;
const trail = options.particles.move.trail;
const fillColor = colorToRgb(trail.fillColor);
if (fillColor) {
const trail = options.particles.move.trail;
this.trailFillColor = {
r: fillColor.r,
g: fillColor.g,
b: fillColor.b,
a: 1 / trail.length
};
}
}
getPluginParticleColors(particle) {
let fColor;
let sColor;
for (const [, plugin] of this.container.plugins) {
if (!fColor && plugin.particleFillColor) {
fColor = colorToHsl(plugin.particleFillColor(particle));
}
if (!sColor && plugin.particleStrokeColor) {
sColor = colorToHsl(plugin.particleStrokeColor(particle));
}
if (fColor && sColor) {
break;
}
}
return [ fColor, sColor ];
}
initStyle() {
const element = this.element, options = this.container.actualOptions;
if (!element) {
return;
}
const originalStyle = this.originalStyle;
if (options.fullScreen.enable) {
this.originalStyle = deepExtend({}, element.style);
element.style.setProperty("position", "fixed", "important");
element.style.setProperty("z-index", options.fullScreen.zIndex.toString(10), "important");
element.style.setProperty("top", "0", "important");
element.style.setProperty("left", "0", "important");
element.style.setProperty("width", "100%", "important");
element.style.setProperty("height", "100%", "important");
} else if (originalStyle) {
element.style.position = originalStyle.position;
element.style.zIndex = originalStyle.zIndex;
element.style.top = originalStyle.top;
element.style.left = originalStyle.left;
element.style.width = originalStyle.width;
element.style.height = originalStyle.height;
}
for (const key in options.style) {
if (!key || !options.style) {
continue;
}
const value = options.style[key];
if (!value) {
continue;
}
element.style.setProperty(key, value, "important");
}
}
paintBase(baseColor) {
this.draw((ctx => {
paintBase(ctx, this.size, baseColor);
}));
}
lineStyle(p1, p2) {
return this.draw((ctx => {
const options = this.container.actualOptions;
const connectOptions = options.interactivity.modes.connect;
return gradient(ctx, p1, p2, connectOptions.links.opacity);
}));
}
}
class Trail_Trail {
constructor() {
this.delay = 1;
this.pauseOnStop = false;
this.quantity = 1;
}
load(data) {
if (data === undefined) {
return;
}
if (data.delay !== undefined) {
this.delay = data.delay;
}
if (data.quantity !== undefined) {
this.quantity = data.quantity;
}
if (data.particles !== undefined) {
this.particles = deepExtend({}, data.particles);
}
if (data.pauseOnStop !== undefined) {
this.pauseOnStop = data.pauseOnStop;
}
}
}
class Modes_Modes {
constructor() {
this.attract = new Attract;
this.bounce = new Bounce;
this.bubble = new Bubble;
this.connect = new Connect;
this.grab = new Grab;
this.light = new Light;
this.push = new Push;
this.remove = new Remove;
this.repulse = new Repulse;
this.slow = new Slow;
this.trail = new Trail;
}
load(data) {
if (data === undefined) {
return;
}
this.attract.load(data.attract);
this.bubble.load(data.bubble);