UNPKG

tsparticles-basic

Version:

Easily create highly customizable particle 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,558 lines (1,536 loc) 196 kB
/*! * 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 * v2.12.0 */ (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]; } })(this, () => { return /******/ (() => { // webpackBootstrap /******/ "use strict"; /******/ // The require scope /******/ var __webpack_require__ = {}; /******/ /************************************************************************/ /******/ /* webpack/runtime/define property getters */ /******/ (() => { /******/ // define getter functions for harmony exports /******/ __webpack_require__.d = (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] }); /******/ } /******/ } /******/ }; /******/ })(); /******/ /******/ /* webpack/runtime/hasOwnProperty shorthand */ /******/ (() => { /******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop)) /******/ })(); /******/ /******/ /* webpack/runtime/make namespace object */ /******/ (() => { /******/ // define __esModule on exports /******/ __webpack_require__.r = (exports) => { /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); /******/ } /******/ Object.defineProperty(exports, '__esModule', { value: true }); /******/ }; /******/ })(); /******/ /************************************************************************/ var __webpack_exports__ = {}; // ESM COMPAT FLAG __webpack_require__.r(__webpack_exports__); // EXPORTS __webpack_require__.d(__webpack_exports__, { AnimatableColor: () => (/* reexport */ AnimatableColor), AnimationOptions: () => (/* reexport */ AnimationOptions), AnimationValueWithRandom: () => (/* reexport */ AnimationValueWithRandom), Background: () => (/* reexport */ Background), BackgroundMask: () => (/* reexport */ BackgroundMask), BackgroundMaskCover: () => (/* reexport */ BackgroundMaskCover), Circle: () => (/* reexport */ Circle), ClickEvent: () => (/* reexport */ ClickEvent), Collisions: () => (/* reexport */ Collisions), CollisionsAbsorb: () => (/* reexport */ CollisionsAbsorb), CollisionsOverlap: () => (/* reexport */ CollisionsOverlap), ColorAnimation: () => (/* reexport */ ColorAnimation), DivEvent: () => (/* reexport */ DivEvent), Events: () => (/* reexport */ Events), ExternalInteractorBase: () => (/* reexport */ ExternalInteractorBase), FullScreen: () => (/* reexport */ FullScreen), HoverEvent: () => (/* reexport */ HoverEvent), HslAnimation: () => (/* reexport */ HslAnimation), HslColorManager: () => (/* reexport */ HslColorManager), Interactivity: () => (/* reexport */ Interactivity), ManualParticle: () => (/* reexport */ ManualParticle), Modes: () => (/* reexport */ Modes), Move: () => (/* reexport */ Move), MoveAngle: () => (/* reexport */ MoveAngle), MoveAttract: () => (/* reexport */ MoveAttract), MoveCenter: () => (/* reexport */ MoveCenter), MoveGravity: () => (/* reexport */ MoveGravity), MovePath: () => (/* reexport */ MovePath), MoveTrail: () => (/* reexport */ MoveTrail), Opacity: () => (/* reexport */ Opacity), OpacityAnimation: () => (/* reexport */ OpacityAnimation), Options: () => (/* reexport */ Options), OptionsColor: () => (/* reexport */ OptionsColor), OutModes: () => (/* reexport */ OutModes), Parallax: () => (/* reexport */ Parallax), ParticlesBounce: () => (/* reexport */ ParticlesBounce), ParticlesBounceFactor: () => (/* reexport */ ParticlesBounceFactor), ParticlesDensity: () => (/* reexport */ ParticlesDensity), ParticlesInteractorBase: () => (/* reexport */ ParticlesInteractorBase), ParticlesNumber: () => (/* reexport */ ParticlesNumber), ParticlesOptions: () => (/* reexport */ ParticlesOptions), Point: () => (/* reexport */ Point), Range: () => (/* reexport */ Range), RangedAnimationOptions: () => (/* reexport */ RangedAnimationOptions), RangedAnimationValueWithRandom: () => (/* reexport */ RangedAnimationValueWithRandom), Rectangle: () => (/* reexport */ Rectangle), ResizeEvent: () => (/* reexport */ ResizeEvent), Responsive: () => (/* reexport */ Responsive), RgbColorManager: () => (/* reexport */ RgbColorManager), Shadow: () => (/* reexport */ Shadow), Shape: () => (/* reexport */ Shape), Size: () => (/* reexport */ Size), SizeAnimation: () => (/* reexport */ SizeAnimation), Spin: () => (/* reexport */ Spin), Stroke: () => (/* reexport */ Stroke), Theme: () => (/* reexport */ Theme), ThemeDefault: () => (/* reexport */ ThemeDefault), ValueWithRandom: () => (/* reexport */ ValueWithRandom), Vector: () => (/* reexport */ Vector), Vector3d: () => (/* reexport */ Vector3d), ZIndex: () => (/* reexport */ ZIndex), addColorManager: () => (/* reexport */ addColorManager), addEasing: () => (/* reexport */ addEasing), alterHsl: () => (/* reexport */ alterHsl), areBoundsInside: () => (/* reexport */ areBoundsInside), arrayRandomIndex: () => (/* reexport */ arrayRandomIndex), calcExactPositionOrRandomFromSize: () => (/* reexport */ calcExactPositionOrRandomFromSize), calcExactPositionOrRandomFromSizeRanged: () => (/* reexport */ calcExactPositionOrRandomFromSizeRanged), calcPositionFromSize: () => (/* reexport */ calcPositionFromSize), calcPositionOrRandomFromSize: () => (/* reexport */ calcPositionOrRandomFromSize), calcPositionOrRandomFromSizeRanged: () => (/* reexport */ calcPositionOrRandomFromSizeRanged), calculateBounds: () => (/* reexport */ calculateBounds), circleBounce: () => (/* reexport */ circleBounce), circleBounceDataFromParticle: () => (/* reexport */ circleBounceDataFromParticle), clamp: () => (/* reexport */ clamp), clear: () => (/* reexport */ clear), collisionVelocity: () => (/* reexport */ collisionVelocity), colorMix: () => (/* reexport */ colorMix), colorToHsl: () => (/* reexport */ colorToHsl), colorToRgb: () => (/* reexport */ colorToRgb), deepExtend: () => (/* reexport */ deepExtend), divMode: () => (/* reexport */ divMode), divModeExecute: () => (/* reexport */ divModeExecute), drawLine: () => (/* reexport */ drawLine), drawParticle: () => (/* reexport */ drawParticle), drawParticlePlugin: () => (/* reexport */ drawParticlePlugin), drawPlugin: () => (/* reexport */ drawPlugin), drawShape: () => (/* reexport */ drawShape), drawShapeAfterEffect: () => (/* reexport */ drawShapeAfterEffect), drawTriangle: () => (/* reexport */ drawTriangle), errorPrefix: () => (/* reexport */ errorPrefix), executeOnSingleOrMultiple: () => (/* reexport */ executeOnSingleOrMultiple), findItemFromSingleOrMultiple: () => (/* reexport */ findItemFromSingleOrMultiple), generatedAttribute: () => (/* reexport */ generatedAttribute), getDistance: () => (/* reexport */ getDistance), getDistances: () => (/* reexport */ getDistances), getEasing: () => (/* reexport */ getEasing), getHslAnimationFromHsl: () => (/* reexport */ getHslAnimationFromHsl), getHslFromAnimation: () => (/* reexport */ getHslFromAnimation), getLinkColor: () => (/* reexport */ getLinkColor), getLinkRandomColor: () => (/* reexport */ getLinkRandomColor), getLogger: () => (/* reexport */ getLogger), getParticleBaseVelocity: () => (/* reexport */ getParticleBaseVelocity), getParticleDirectionAngle: () => (/* reexport */ getParticleDirectionAngle), getPosition: () => (/* reexport */ getPosition), getRandom: () => (/* reexport */ getRandom), getRandomRgbColor: () => (/* reexport */ getRandomRgbColor), getRangeMax: () => (/* reexport */ getRangeMax), getRangeMin: () => (/* reexport */ getRangeMin), getRangeValue: () => (/* reexport */ getRangeValue), getSize: () => (/* reexport */ getSize), getStyleFromHsl: () => (/* reexport */ getStyleFromHsl), getStyleFromRgb: () => (/* reexport */ getStyleFromRgb), getValue: () => (/* reexport */ getValue), hasMatchMedia: () => (/* reexport */ hasMatchMedia), hslToRgb: () => (/* reexport */ hslToRgb), hslaToRgba: () => (/* reexport */ hslaToRgba), initParticleNumericAnimationValue: () => (/* reexport */ initParticleNumericAnimationValue), isArray: () => (/* reexport */ isArray), isBoolean: () => (/* reexport */ isBoolean), isDivModeEnabled: () => (/* reexport */ isDivModeEnabled), isFunction: () => (/* reexport */ isFunction), isInArray: () => (/* reexport */ isInArray), isNumber: () => (/* reexport */ isNumber), isObject: () => (/* reexport */ isObject), isPointInside: () => (/* reexport */ isPointInside), isSsr: () => (/* reexport */ isSsr), isString: () => (/* reexport */ isString), itemFromArray: () => (/* reexport */ itemFromArray), itemFromSingleOrMultiple: () => (/* reexport */ itemFromSingleOrMultiple), loadBasic: () => (/* reexport */ loadBasic), loadFont: () => (/* reexport */ loadFont), loadOptions: () => (/* reexport */ loadOptions), loadParticlesOptions: () => (/* reexport */ loadParticlesOptions), mix: () => (/* reexport */ mix), mouseDownEvent: () => (/* reexport */ mouseDownEvent), mouseLeaveEvent: () => (/* reexport */ mouseLeaveEvent), mouseMoveEvent: () => (/* reexport */ mouseMoveEvent), mouseOutEvent: () => (/* reexport */ mouseOutEvent), mouseUpEvent: () => (/* reexport */ mouseUpEvent), paintBase: () => (/* reexport */ paintBase), paintImage: () => (/* reexport */ paintImage), parseAlpha: () => (/* reexport */ parseAlpha), randomInRange: () => (/* reexport */ randomInRange), rangeColorToHsl: () => (/* reexport */ rangeColorToHsl), rangeColorToRgb: () => (/* reexport */ rangeColorToRgb), rectBounce: () => (/* reexport */ rectBounce), resizeEvent: () => (/* reexport */ resizeEvent), rgbToHsl: () => (/* reexport */ rgbToHsl), safeMatchMedia: () => (/* reexport */ safeMatchMedia), safeMutationObserver: () => (/* reexport */ safeMutationObserver), setLogger: () => (/* reexport */ setLogger), setRandom: () => (/* reexport */ setRandom), setRangeValue: () => (/* reexport */ setRangeValue), singleDivModeExecute: () => (/* reexport */ singleDivModeExecute), stringToAlpha: () => (/* reexport */ stringToAlpha), stringToRgb: () => (/* reexport */ stringToRgb), touchCancelEvent: () => (/* reexport */ touchCancelEvent), touchEndEvent: () => (/* reexport */ touchEndEvent), touchMoveEvent: () => (/* reexport */ touchMoveEvent), touchStartEvent: () => (/* reexport */ touchStartEvent), tsParticles: () => (/* reexport */ tsParticles), visibilityChangeEvent: () => (/* reexport */ visibilityChangeEvent) }); ;// CONCATENATED MODULE: ../../engine/dist/esm/Core/Utils/Constants.js const generatedAttribute = "generated"; const mouseDownEvent = "pointerdown"; const mouseUpEvent = "pointerup"; const mouseLeaveEvent = "pointerleave"; const mouseOutEvent = "pointerout"; const mouseMoveEvent = "pointermove"; const touchStartEvent = "touchstart"; const touchEndEvent = "touchend"; const touchMoveEvent = "touchmove"; const touchCancelEvent = "touchcancel"; const resizeEvent = "resize"; const visibilityChangeEvent = "visibilitychange"; const errorPrefix = "tsParticles - Error"; ;// CONCATENATED MODULE: ../../engine/dist/esm/Core/Utils/Vector3d.js class Vector3d { constructor(xOrCoords, y, z) { this._updateFromAngle = (angle, length) => { this.x = Math.cos(angle) * length; this.y = Math.sin(angle) * length; }; if (!isNumber(xOrCoords) && xOrCoords) { this.x = xOrCoords.x; this.y = xOrCoords.y; const coords3d = xOrCoords; this.z = coords3d.z ? coords3d.z : 0; } else if (xOrCoords !== undefined && y !== undefined) { this.x = xOrCoords; this.y = y; this.z = z ?? 0; } else { throw new Error(`${errorPrefix} Vector3d not initialized correctly`); } } static get origin() { return Vector3d.create(0, 0, 0); } get angle() { return Math.atan2(this.y, this.x); } set angle(angle) { this._updateFromAngle(angle, this.length); } get length() { return Math.sqrt(this.getLengthSq()); } set length(length) { this._updateFromAngle(this.angle, length); } static clone(source) { return Vector3d.create(source.x, source.y, source.z); } static create(x, y, z) { return new Vector3d(x, y, z); } add(v) { return Vector3d.create(this.x + v.x, this.y + v.y, this.z + v.z); } addTo(v) { this.x += v.x; this.y += v.y; this.z += v.z; } copy() { return Vector3d.clone(this); } distanceTo(v) { return this.sub(v).length; } distanceToSq(v) { return this.sub(v).getLengthSq(); } div(n) { return Vector3d.create(this.x / n, this.y / n, this.z / n); } divTo(n) { this.x /= n; this.y /= n; this.z /= n; } getLengthSq() { return this.x ** 2 + this.y ** 2; } mult(n) { return Vector3d.create(this.x * n, this.y * n, this.z * n); } multTo(n) { this.x *= n; this.y *= n; this.z *= n; } normalize() { const length = this.length; if (length != 0) { this.multTo(1.0 / length); } } rotate(angle) { return Vector3d.create(this.x * Math.cos(angle) - this.y * Math.sin(angle), this.x * Math.sin(angle) + this.y * Math.cos(angle), 0); } setTo(c) { this.x = c.x; this.y = c.y; const v3d = c; this.z = v3d.z ? v3d.z : 0; } sub(v) { return Vector3d.create(this.x - v.x, this.y - v.y, this.z - v.z); } subFrom(v) { this.x -= v.x; this.y -= v.y; this.z -= v.z; } } ;// CONCATENATED MODULE: ../../engine/dist/esm/Core/Utils/Vector.js class Vector extends Vector3d { constructor(xOrCoords, y) { super(xOrCoords, y, 0); } static get origin() { return Vector.create(0, 0); } static clone(source) { return Vector.create(source.x, source.y); } static create(x, y) { return new Vector(x, y); } } ;// CONCATENATED MODULE: ../../engine/dist/esm/Utils/Utils.js const _logger = { debug: console.debug, error: console.error, info: console.info, log: console.log, verbose: console.log, warning: console.warn }; function setLogger(logger) { _logger.debug = logger.debug || _logger.debug; _logger.error = logger.error || _logger.error; _logger.info = logger.info || _logger.info; _logger.log = logger.log || _logger.log; _logger.verbose = logger.verbose || _logger.verbose; _logger.warning = logger.warning || _logger.warning; } function getLogger() { return _logger; } 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) / 2 && velocity > 0 || pSide.min <= rectSide.max && pSide.min > (rectSide.max + rectSide.min) / 2 && velocity < 0) { res.velocity = velocity * -factor; res.bounced = true; } return res; } function checkSelector(element, selectors) { const res = executeOnSingleOrMultiple(selectors, selector => { return element.matches(selector); }); return isArray(res) ? res.some(t => t) : res; } function isSsr() { return typeof window === "undefined" || !window || typeof window.document === "undefined" || !window.document; } function hasMatchMedia() { return !isSsr() && typeof matchMedia !== "undefined"; } function safeMatchMedia(query) { if (!hasMatchMedia()) { return; } return matchMedia(query); } function safeMutationObserver(callback) { if (isSsr() || typeof MutationObserver === "undefined") { return; } return new MutationObserver(callback); } function isInArray(value, array) { return value === array || isArray(array) && array.indexOf(value) > -1; } async function loadFont(font, weight) { try { await document.fonts.load(`${weight ?? "400"} 36px '${font ?? "Verdana"}'`); } catch {} } function arrayRandomIndex(array) { return Math.floor(getRandom() * array.length); } function itemFromArray(array, index, useIndex = true) { return array[index !== undefined && useIndex ? index % array.length : arrayRandomIndex(array)]; } function isPointInside(point, size, offset, radius, direction) { return areBoundsInside(calculateBounds(point, radius ?? 0), size, offset, direction); } function areBoundsInside(bounds, size, offset, direction) { let inside = true; if (!direction || direction === "bottom") { inside = bounds.top < size.height + offset.x; } if (inside && (!direction || direction === "left")) { inside = bounds.right > offset.x; } if (inside && (!direction || direction === "right")) { inside = bounds.left < size.width + offset.y; } if (inside && (!direction || direction === "top")) { inside = bounds.bottom > offset.y; } return inside; } function calculateBounds(point, radius) { return { bottom: point.y + radius, left: point.x - radius, right: point.x + radius, top: point.y - radius }; } function deepExtend(destination, ...sources) { for (const source of sources) { if (source === undefined || source === null) { continue; } if (!isObject(source)) { destination = source; continue; } const sourceIsArray = Array.isArray(source); if (sourceIsArray && (isObject(destination) || !destination || !Array.isArray(destination))) { destination = []; } else if (!sourceIsArray && (isObject(destination) || !destination || Array.isArray(destination))) { destination = {}; } for (const key in source) { if (key === "__proto__") { continue; } const sourceDict = source, value = sourceDict[key], destDict = destination; destDict[key] = isObject(value) && Array.isArray(value) ? value.map(v => deepExtend(destDict[key], v)) : deepExtend(destDict[key], value); } } return destination; } function isDivModeEnabled(mode, divs) { return !!findItemFromSingleOrMultiple(divs, t => t.enable && isInArray(mode, t.mode)); } function divModeExecute(mode, divs, callback) { executeOnSingleOrMultiple(divs, div => { const divMode = div.mode, divEnabled = div.enable; if (divEnabled && isInArray(mode, divMode)) { singleDivModeExecute(div, callback); } }); } function singleDivModeExecute(div, callback) { const selectors = div.selectors; executeOnSingleOrMultiple(selectors, selector => { callback(selector, div); }); } function divMode(divs, element) { if (!element || !divs) { return; } return findItemFromSingleOrMultiple(divs, div => { return checkSelector(element, div.selectors); }); } function circleBounceDataFromParticle(p) { return { position: p.getPosition(), radius: p.getRadius(), mass: p.getMass(), velocity: p.velocity, factor: Vector.create(getValue(p.options.bounce.horizontal), getValue(p.options.bounce.vertical)) }; } function circleBounce(p1, p2) { const { x: xVelocityDiff, y: yVelocityDiff } = p1.velocity.sub(p2.velocity), [pos1, pos2] = [p1.position, p2.position], { dx: xDist, dy: yDist } = getDistances(pos2, pos1); if (xVelocityDiff * xDist + yVelocityDiff * yDist < 0) { return; } const angle = -Math.atan2(yDist, xDist), m1 = p1.mass, m2 = p2.mass, u1 = p1.velocity.rotate(angle), u2 = p2.velocity.rotate(angle), v1 = collisionVelocity(u1, u2, m1, m2), v2 = collisionVelocity(u2, u1, m1, m2), vFinal1 = v1.rotate(-angle), vFinal2 = v2.rotate(-angle); p1.velocity.x = vFinal1.x * p1.factor.x; p1.velocity.y = vFinal1.y * p1.factor.y; p2.velocity.x = vFinal2.x * p2.factor.x; p2.velocity.y = vFinal2.y * p2.factor.y; } function rectBounce(particle, divBounds) { const pPos = particle.getPosition(), size = particle.getRadius(), bounds = calculateBounds(pPos, size), 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: getValue(particle.options.bounce.horizontal) }); 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: getValue(particle.options.bounce.vertical) }); if (resV.bounced) { if (resV.velocity !== undefined) { particle.velocity.y = resV.velocity; } if (resV.position !== undefined) { particle.position.y = resV.position; } } } function executeOnSingleOrMultiple(obj, callback) { return isArray(obj) ? obj.map((item, index) => callback(item, index)) : callback(obj, 0); } function itemFromSingleOrMultiple(obj, index, useIndex) { return isArray(obj) ? itemFromArray(obj, index, useIndex) : obj; } function findItemFromSingleOrMultiple(obj, callback) { return isArray(obj) ? obj.find((t, index) => callback(t, index)) : callback(obj, 0) ? obj : undefined; } function initParticleNumericAnimationValue(options, pxRatio) { const valueRange = options.value, animationOptions = options.animation, res = { delayTime: getRangeValue(animationOptions.delay) * 1000, enable: animationOptions.enable, value: getRangeValue(options.value) * pxRatio, max: getRangeMax(valueRange) * pxRatio, min: getRangeMin(valueRange) * pxRatio, loops: 0, maxLoops: getRangeValue(animationOptions.count), time: 0 }; if (animationOptions.enable) { res.decay = 1 - getRangeValue(animationOptions.decay); switch (animationOptions.mode) { case "increase": res.status = "increasing"; break; case "decrease": res.status = "decreasing"; break; case "random": res.status = getRandom() >= 0.5 ? "increasing" : "decreasing"; break; } const autoStatus = animationOptions.mode === "auto"; switch (animationOptions.startValue) { case "min": res.value = res.min; if (autoStatus) { res.status = "increasing"; } break; case "max": res.value = res.max; if (autoStatus) { res.status = "decreasing"; } break; case "random": default: res.value = randomInRange(res); if (autoStatus) { res.status = getRandom() >= 0.5 ? "increasing" : "decreasing"; } break; } } res.initialValue = res.value; return res; } function getPositionOrSize(positionOrSize, canvasSize) { const isPercent = positionOrSize.mode === "percent"; if (!isPercent) { const { mode: _, ...rest } = positionOrSize; return rest; } const isPosition = ("x" in positionOrSize); if (isPosition) { return { x: positionOrSize.x / 100 * canvasSize.width, y: positionOrSize.y / 100 * canvasSize.height }; } else { return { width: positionOrSize.width / 100 * canvasSize.width, height: positionOrSize.height / 100 * canvasSize.height }; } } function getPosition(position, canvasSize) { return getPositionOrSize(position, canvasSize); } function getSize(size, canvasSize) { return getPositionOrSize(size, canvasSize); } function isBoolean(arg) { return typeof arg === "boolean"; } function isString(arg) { return typeof arg === "string"; } function isNumber(arg) { return typeof arg === "number"; } function isFunction(arg) { return typeof arg === "function"; } function isObject(arg) { return typeof arg === "object" && arg !== null; } function isArray(arg) { return Array.isArray(arg); } ;// CONCATENATED MODULE: ../../engine/dist/esm/Utils/NumberUtils.js let _random = Math.random; const easings = new Map(); function addEasing(name, easing) { if (easings.get(name)) { return; } easings.set(name, easing); } function getEasing(name) { return easings.get(name) || (value => value); } function setRandom(rnd = Math.random) { _random = rnd; } function getRandom() { return clamp(_random(), 0, 1 - 1e-16); } function clamp(num, min, max) { return Math.min(Math.max(num, min), max); } function mix(comp1, comp2, weight1, weight2) { return Math.floor((comp1 * weight1 + comp2 * weight2) / (weight1 + weight2)); } function randomInRange(r) { const max = getRangeMax(r); let min = getRangeMin(r); if (max === min) { min = 0; } return getRandom() * (max - min) + min; } function getRangeValue(value) { return isNumber(value) ? value : randomInRange(value); } function getRangeMin(value) { return isNumber(value) ? value : value.min; } function getRangeMax(value) { return isNumber(value) ? value : value.max; } function setRangeValue(source, value) { if (source === value || value === undefined && isNumber(source)) { return source; } const min = getRangeMin(source), max = getRangeMax(source); return value !== undefined ? { min: Math.min(min, value), max: Math.max(max, value) } : setRangeValue(min, max); } function getValue(options) { const random = options.random, { enable, minimumValue } = isBoolean(random) ? { enable: random, minimumValue: 0 } : random; return enable ? getRangeValue(setRangeValue(options.value, minimumValue)) : getRangeValue(options.value); } function getDistances(pointA, pointB) { const dx = pointA.x - pointB.x, dy = pointA.y - pointB.y; return { dx: dx, dy: dy, distance: Math.sqrt(dx ** 2 + dy ** 2) }; } function getDistance(pointA, pointB) { return getDistances(pointA, pointB).distance; } function getParticleDirectionAngle(direction, position, center) { if (isNumber(direction)) { return direction * Math.PI / 180; } switch (direction) { case "top": return -Math.PI / 2; case "top-right": return -Math.PI / 4; case "right": return 0; case "bottom-right": return Math.PI / 4; case "bottom": return Math.PI / 2; case "bottom-left": return 3 * Math.PI / 4; case "left": return Math.PI; case "top-left": return -3 * Math.PI / 4; case "inside": return Math.atan2(center.y - position.y, center.x - position.x); case "outside": return Math.atan2(position.y - center.y, position.x - center.x); default: return getRandom() * Math.PI * 2; } } function getParticleBaseVelocity(direction) { const baseVelocity = Vector.origin; baseVelocity.length = 1; baseVelocity.angle = direction; return baseVelocity; } function collisionVelocity(v1, v2, m1, m2) { return Vector.create(v1.x * (m1 - m2) / (m1 + m2) + v2.x * 2 * m2 / (m1 + m2), v1.y); } function calcPositionFromSize(data) { return data.position && data.position.x !== undefined && data.position.y !== undefined ? { x: data.position.x * data.size.width / 100, y: data.position.y * data.size.height / 100 } : undefined; } function calcPositionOrRandomFromSize(data) { return { x: (data.position?.x ?? getRandom() * 100) * data.size.width / 100, y: (data.position?.y ?? getRandom() * 100) * data.size.height / 100 }; } function calcPositionOrRandomFromSizeRanged(data) { const position = { x: data.position?.x !== undefined ? getRangeValue(data.position.x) : undefined, y: data.position?.y !== undefined ? getRangeValue(data.position.y) : undefined }; return calcPositionOrRandomFromSize({ size: data.size, position }); } function calcExactPositionOrRandomFromSize(data) { return { x: data.position?.x ?? getRandom() * data.size.width, y: data.position?.y ?? getRandom() * data.size.height }; } function calcExactPositionOrRandomFromSizeRanged(data) { const position = { x: data.position?.x !== undefined ? getRangeValue(data.position.x) : undefined, y: data.position?.y !== undefined ? getRangeValue(data.position.y) : undefined }; return calcExactPositionOrRandomFromSize({ size: data.size, position }); } function parseAlpha(input) { return input ? input.endsWith("%") ? parseFloat(input) / 100 : parseFloat(input) : 1; } ;// CONCATENATED MODULE: ../../move/base/dist/esm/Utils.js function applyDistance(particle) { const initialPosition = particle.initialPosition, { dx, dy } = getDistances(initialPosition, particle.position), dxFixed = Math.abs(dx), dyFixed = Math.abs(dy), { maxDistance } = particle.retina, hDistance = maxDistance.horizontal, vDistance = 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 *= -getRandom(); } if (vDistance && (pos.y < initialPosition.y && vel.y < 0 || pos.y > initialPosition.y && vel.y > 0)) { vel.y *= -getRandom(); } } } function move(particle, moveOptions, moveSpeed, maxSpeed, moveDrift, delta) { applyPath(particle, delta); const gravityOptions = particle.gravity, gravityFactor = gravityOptions?.enable && gravityOptions.inverse ? -1 : 1; if (moveDrift && moveSpeed) { particle.velocity.x += moveDrift * delta.factor / (60 * moveSpeed); } if (gravityOptions?.enable && moveSpeed) { particle.velocity.y += gravityFactor * (gravityOptions.acceleration * delta.factor) / (60 * moveSpeed); } const decay = particle.moveDecay; particle.velocity.multTo(decay); const velocity = particle.velocity.mult(moveSpeed); 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; velocity.multTo(zVelocityFactor); const { position } = particle; position.addTo(velocity); if (moveOptions.vibrate) { position.x += Math.sin(position.x * Math.cos(position.y)); position.y += Math.cos(position.y * Math.sin(position.x)); } } function spin(particle, moveSpeed) { const container = particle.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); } function applyPath(particle, delta) { const particlesOptions = particle.options, pathOptions = particlesOptions.move.path, pathEnabled = pathOptions.enable; if (!pathEnabled) { return; } if (particle.lastPathTime <= particle.pathDelay) { particle.lastPathTime += delta.value; return; } const path = particle.pathGenerator?.generate(particle, delta); if (path) { 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; } function getProximitySpeedFactor(particle) { return particle.slow.inRange ? particle.slow.factor : 1; } ;// CONCATENATED MODULE: ../../move/base/dist/esm/BaseMover.js const diffFactor = 2; class BaseMover { constructor() { this._initSpin = particle => { const container = particle.container, options = particle.options, spinOptions = options.move.spin; if (!spinOptions.enable) { return; } const spinPos = spinOptions.position ?? { x: 50, y: 50 }, spinCenter = { x: spinPos.x / 100 * container.canvas.size.width, y: spinPos.y / 100 * container.canvas.size.height }, pos = particle.getPosition(), distance = getDistance(pos, spinCenter), spinAcceleration = getRangeValue(spinOptions.acceleration); particle.retina.spinAcceleration = spinAcceleration * container.retina.pixelRatio; particle.spin = { center: spinCenter, direction: particle.velocity.x >= 0 ? "clockwise" : "counter-clockwise", angle: particle.velocity.angle, radius: distance, acceleration: particle.retina.spinAcceleration }; }; } init(particle) { const options = particle.options, gravityOptions = options.move.gravity; particle.gravity = { enable: gravityOptions.enable, acceleration: getRangeValue(gravityOptions.acceleration), inverse: gravityOptions.inverse }; this._initSpin(particle); } isEnabled(particle) { return !particle.destroyed && particle.options.move.enable; } move(particle, delta) { const particleOptions = particle.options, moveOptions = particleOptions.move; if (!moveOptions.enable) { return; } const container = particle.container, pxRatio = container.retina.pixelRatio, slowFactor = getProximitySpeedFactor(particle), baseSpeed = (particle.retina.moveSpeed ??= getRangeValue(moveOptions.speed) * pxRatio) * container.retina.reduceFactor, moveDrift = particle.retina.moveDrift ??= getRangeValue(particle.options.move.drift) * pxRatio, maxSize = getRangeMax(particleOptions.size.value) * pxRatio, sizeFactor = moveOptions.size ? particle.getRadius() / maxSize : 1, moveSpeed = baseSpeed * sizeFactor * slowFactor * (delta.factor || 1) / diffFactor, maxSpeed = particle.retina.maxSpeed ?? container.retina.maxSpeed; if (moveOptions.spin.enable) { spin(particle, moveSpeed); } else { move(particle, moveOptions, moveSpeed, maxSpeed, moveDrift, delta); } applyDistance(particle); } } ;// CONCATENATED MODULE: ../../move/base/dist/esm/index.js async function loadBaseMover(engine, refresh = true) { await engine.addMover("base", () => new BaseMover(), refresh); } ;// CONCATENATED MODULE: ../../shapes/circle/dist/esm/CircleDrawer.js class CircleDrawer { draw(context, particle, radius) { if (!particle.circleRange) { particle.circleRange = { min: 0, max: Math.PI * 2 }; } const circleRange = particle.circleRange; context.arc(0, 0, radius, circleRange.min, circleRange.max, false); } getSidesCount() { return 12; } particleInit(container, particle) { const shapeData = particle.shapeData, angle = shapeData?.angle ?? { max: 360, min: 0 }; particle.circleRange = !isObject(angle) ? { min: 0, max: angle * Math.PI / 180 } : { min: angle.min * Math.PI / 180, max: angle.max * Math.PI / 180 }; } } ;// CONCATENATED MODULE: ../../shapes/circle/dist/esm/index.js async function loadCircleShape(engine, refresh = true) { await engine.addShape("circle", new CircleDrawer(), refresh); } ;// CONCATENATED MODULE: ../../engine/dist/esm/Utils/ColorUtils.js const randomColorValue = "random", midColorValue = "mid", colorManagers = new Map(); function addColorManager(manager) { colorManagers.set(manager.key, manager); } function hue2rgb(p, q, t) { if (t < 0) { t += 1; } if (t > 1) { t -= 1; } if (t < 1 / 6) { return p + (q - p) * 6 * t; } if (t < 1 / 2) { return q; } if (t < 2 / 3) { return p + (q - p) * (2 / 3 - t) * 6; } return p; } function stringToRgba(input) { for (const [, manager] of colorManagers) { if (input.startsWith(manager.stringPrefix)) { return manager.parseString(input); } } const shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])([a-f\d])?$/i, hexFixed = input.replace(shorthandRegex, (_, r, g, b, a) => { return r + r + g + g + b + b + (a !== undefined ? a + a : ""); }), regex = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})?$/i, result = regex.exec(hexFixed); return result ? { a: result[4] !== undefined ? parseInt(result[4], 16) / 0xff : 1, b: parseInt(result[3], 16), g: parseInt(result[2], 16), r: parseInt(result[1], 16) } : undefined; } function rangeColorToRgb(input, index, useIndex = true) { if (!input) { return; } const color = isString(input) ? { value: input } : input; if (isString(color.value)) { return colorToRgb(color.value, index, useIndex); } if (isArray(color.value)) { return rangeColorToRgb({ value: itemFromArray(color.value, index, useIndex) }); } for (const [, manager] of colorManagers) { const res = manager.handleRangeColor(color); if (res) { return res; } } } function colorToRgb(input, index, useIndex = true) { if (!input) { return; } const color = isString(input) ? { value: input } : input; if (isString(color.value)) { return color.value === randomColorValue ? getRandomRgbColor() : stringToRgb(color.value); } if (isArray(color.value)) { return colorToRgb({ value: itemFromArray(color.value, index, useIndex) }); } for (const [, manager] of colorManagers) { const res = manager.handleColor(color); if (res) { return res; } } } function colorToHsl(color, index, useIndex = true) { const rgb = colorToRgb(color, index, useIndex); return rgb ? rgbToHsl(rgb) : undefined; } function rangeColorToHsl(color, index, useIndex = true) { const rgb = rangeColorToRgb(color, index, useIndex); return rgb ? rgbToHsl(rgb) : undefined; } function rgbToHsl(color) { const r1 = color.r / 255, g1 = color.g / 255, b1 = color.b / 255, max = Math.max(r1, g1, b1), min = Math.min(r1, g1, b1), res = { h: 0, l: (max + min) / 2, s: 0 }; if (max !== min) { res.s = res.l < 0.5 ? (max - min) / (max + min) : (max - min) / (2.0 - max - min); res.h = r1 === max ? (g1 - b1) / (max - min) : res.h = g1 === max ? 2.0 + (b1 - r1) / (max - min) : 4.0 + (r1 - g1) / (max - min); } res.l *= 100; res.s *= 100; res.h *= 60; if (res.h < 0) { res.h += 360; } if (res.h >= 360) { res.h -= 360; } return res; } function stringToAlpha(input) { return stringToRgba(input)?.a; } function stringToRgb(input) { return stringToRgba(input); } function hslToRgb(hsl) { const result = { b: 0, g: 0, r: 0 }, hslPercent = { h: hsl.h / 360, l: hsl.l / 100, s: hsl.s / 100 }; if (!hslPercent.s) { result.r = result.g = result.b = hslPercent.l; } else { const q = hslPercent.l < 0.5 ? hslPercent.l * (1 + hslPercent.s) : hslPercent.l + hslPercent.s - hslPercent.l * hslPercent.s, p = 2 * hslPercent.l - q; result.r = hue2rgb(p, q, hslPercent.h + 1 / 3); result.g = hue2rgb(p, q, hslPercent.h); result.b = hue2rgb(p, q, hslPercent.h - 1 / 3); } result.r = Math.floor(result.r * 255); result.g = Math.floor(result.g * 255); result.b = Math.floor(result.b * 255); return result; } function hslaToRgba(hsla) { const rgbResult = hslToRgb(hsla); return { a: hsla.a, b: rgbResult.b, g: rgbResult.g, r: rgbResult.r }; } function getRandomRgbColor(min) { const fixedMin = min ?? 0; return { b: Math.floor(randomInRange(setRangeValue(fixedMin, 256))), g: Math.floor(randomInRange(setRangeValue(fixedMin, 256))), r: Math.floor(randomInRange(setRangeValue(fixedMin, 256))) }; } function getStyleFromRgb(color, opacity) { return `rgba(${color.r}, ${color.g}, ${color.b}, ${opacity ?? 1})`; } function getStyleFromHsl(color, opacity) { return `hsla(${color.h}, ${color.s}%, ${color.l}%, ${opacity ?? 1})`; } function colorMix(color1, color2, size1, size2) { let rgb1 = color1, rgb2 = color2; if (rgb1.r === undefined) { rgb1 = hslToRgb(color1); } if (rgb2.r === undefined) { rgb2 = hslToRgb(color2); } return { b: mix(rgb1.b, rgb2.b, size1, size2), g: mix(rgb1.g, rgb2.g, size1, size2), r: mix(rgb1.r, rgb2.r, size1, size2) }; } function getLinkColor(p1, p2, linkColor) { if (linkColor === randomColorValue) { return getRandomRgbColor(); } else if (linkColor === midColorValue) { const sourceColor = p1.getFillColor() ?? p1.getStrokeColor(), destColor = p2?.getFillColor() ?? p2?.getStrokeColor(); if (sourceColor && destColor && p2) { return colorMix(sourceColor, destColor, p1.getRadius(), p2.getRadius()); } else { const hslColor = sourceColor ?? destColor; if (hslColor) { return hslToRgb(hslColor); } } } else { return linkColor; } } function getLinkRandomColor(optColor, blink, consent) { const color = isString(optColor) ? optColor : optColor.value; if (color === randomColorValue) { if (consent) { return rangeColorToRgb({ value: color }); } if (blink) { return randomColorValue; } return midColorValue; } else if (color === midColorValue) { return midColorValue; } else { return rangeColorToRgb({ value: color }); } } function getHslFromAnimation(animation) { return animation !== undefined ? { h: animation.h.value, s: animation.s.value, l: animation.l.value } : undefined; } function getHslAnimationFromHsl(hsl, animationOptions, reduceFactor) { const resColor = { h: { enable: false, value: hsl.h }, s: { enable: false, value: hsl.s }, l: { enable: false, value: hsl.l } }; if (animationOptions) { setColorAnimation(resColor.h, animationOptions.h, reduceFactor); setColorAnimation(resColor.s, animationOptions.s, reduceFactor); setColorAnimation(resColor.l, animationOptions.l, reduceFactor); } return resColor; } function setColorAnimation(colorValue, colorAnimation, reduceFactor) { colorValue.enable = colorAnimation.enable; if (colorValue.enable) { colorValue.velocity = getRangeValue(colorAnimation.speed) / 100 * reduceFactor; colorValue.decay = 1 - getRangeValue(colorAnimation.decay); colorValue.status = "increasing"; colorValue.loops = 0; colorValue.maxLoops = getRangeValue(colorAnimation.count); colorValue.time = 0; colorValue.delayTime = getRangeValue(colorAnimation.delay) * 1000; if (!colorAnimation.sync) { colorValue.velocity *= getRandom(); colorValue.value *= getRandom(); } colorValue.initialValue = colorValue.value; } else { colorValue.velocity = 0; } } ;// CONCATENATED MODULE: ../../updaters/color/dist/esm/Utils.js function updateColorValue(delta, colorValue, valueAnimation, max, decrease) { if (!colorValue || !valueAnimation.enable || (colorValue.maxLoops ?? 0) > 0 && (colorValue.loops ?? 0) > (colorValue.maxLoops ?? 0)) { return; } if (!colorValue.time) { colorValue.time = 0; } if ((colorValue.delayTime ?? 0) > 0 && colorValue.time < (colorValue.delayTime ?? 0)) { colorValue.time += delta.value; } if ((colorValue.delayTime ?? 0) > 0 && colorValue.time < (colorValue.delayTime ?? 0)) { return; } const offset = randomInRange(valueAnimation.offset), velocity = (colorValue.velocity ?? 0) * delta.factor + offset * 3.6, decay = colorValue.decay ?? 1; if (!decrease || colorValue.status === "increasing") { colorValue.value += velocity; if (colorValue.value > max) { if (!colorValue.loops) { colorValue.loops = 0; } colorValue.loops++; if (decrease) { colorValue.status = "decreasing"; colorValue.value -= colorValue.value % max; } } } else { colorValue.value -= velocity; if (colorValue.value < 0) { if (!colorValue.loops) { colorValue.loops = 0; } colorValue.loops++; colorValue.status = "increasing"; colorValue.value += colorValue.value; } } if (colorValue.velocity && decay !== 1) { colorValue.velocity *= decay; } if (colorValue.value > max) { colorValue.value %= max; } } function updateColor(particle, delta) { const { h: hAnimation, s: sAnimation, l: lAnimation } = particle.options.color.animation, { color } = particle; if (!color) { return; } const { h, s, l } = color; if (h) { updateColorValue(delta, h, hAnimation, 360, false); } if (s) { updateColorValue(delta, s, sAnimation, 100, true); } if (l) { updateColorValue(delta, l, lAnimation, 100, true); } } ;// CONCATENATED MODULE: ../../updaters/color/dist/esm/ColorUpdater.js class ColorUpdater { constructor(container) { this.container = container; } init(particle) { const hslColor = rangeColorToHsl(particle.options.color, particle.id, particle.options.reduceDuplicates); if (hslColor) { particle.color = getHslAnimationFromHsl(hslColor, particle.options.color.animation, this.container.retina.reduceFactor); } } isEnabled(particle) { const { h: hAnimation, s: sAnimation, l: lAnimation } = particle.options.color.animation, { color } = particle; return !particle.destroyed && !particle.spawning && (color?.h.value !== undefined && hAnimation.enable || color?.s.value !== undefined && sAnimation.enable || color?.l.value !== undefined && lAnimation.enable); } update(particle, delta) { updateColor(particle, delta); } } ;// CONCATENATED MODULE: ../../updaters/color/dist/esm/index.js async function loadColorUpdater(engine, refresh = true) { await engine.addParticleUpdater("color", container => new ColorUpdater(container), refresh); } ;// CONCATENATED MODULE: ../../updaters/opacity/dist/esm/Utils.js function checkDestroy(particle, value, minValue, maxValue) { switch (particle.options.opacity.animation.destroy) { case "max": if (value >= maxValue) { particle.destroy(); } break; case "min": if (value <= minValue) { particle.destroy(); } break; } } function updateOpacity(particle, delta) { const data = particle.opacity; if (particle.destroyed || !data?.enable || (data.maxLoops ?? 0) > 0 && (data.loops ?? 0) > (data.maxLoops ?? 0)) { return; } const minValue = data.min, maxValue = data.max, decay = data.decay ?? 1; if (!data.time) { data.time = 0; } if ((data.delayTime ?? 0) > 0 && data.time < (data.delayTime ?? 0)) { data.time += delta.value; } if ((data.delayTime ?? 0) > 0 && data.time < (data.delayTime ?? 0)) { return; } switch (data.status) { case "increasing": if (data.value >= maxValue) { data.status = "decreasing"; if (!data.loops) { data.loops = 0; } data.loops++; } else { data.value += (data.velocity ?? 0) * delta.factor; } break; case "decreasing": if (data.value <= minValue) { data.status = "increasing"; if (!data.loops) { data.loops = 0; } data.loops++; } else { data.value -= (data.velocity ?? 0) * delta.factor; } break; } if (data.velocity && data.decay !== 1) { data.velocity *= decay; } checkDestroy(particle, data.value, minValue, maxValue); if (!particle.destroyed) { data.value = clamp(data.value, minValue, maxValue); } } ;// CONCATENATED MODULE: ../../updaters/opacity/dist/e