tsparticles
Version:
Porting of the abandoned Vincent Garreau's particles.js, converted in TypeScript. Added many new cool features and various bug fixes.
1,641 lines (1,361 loc) • 152 kB
JavaScript
(function(e, a) { for(var i in a) e[i] = a[i]; }(window, /******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId]) {
/******/ return installedModules[moduleId].exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ i: moduleId,
/******/ l: false,
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Flag the module as loaded
/******/ module.l = true;
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/
/******/ // define getter function for harmony exports
/******/ __webpack_require__.d = function(exports, name, getter) {
/******/ if(!__webpack_require__.o(exports, name)) {
/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
/******/ }
/******/ };
/******/
/******/ // define __esModule on exports
/******/ __webpack_require__.r = function(exports) {
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ }
/******/ Object.defineProperty(exports, '__esModule', { value: true });
/******/ };
/******/
/******/ // create a fake namespace object
/******/ // mode & 1: value is a module id, require it
/******/ // mode & 2: merge all properties of value into the ns
/******/ // mode & 4: return value when already ns object
/******/ // mode & 8|1: behave like require
/******/ __webpack_require__.t = function(value, mode) {
/******/ if(mode & 1) value = __webpack_require__(value);
/******/ if(mode & 8) return value;
/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
/******/ var ns = Object.create(null);
/******/ __webpack_require__.r(ns);
/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
/******/ return ns;
/******/ };
/******/
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = function(module) {
/******/ var getter = module && module.__esModule ?
/******/ function getDefault() { return module['default']; } :
/******/ function getModuleExports() { return module; };
/******/ __webpack_require__.d(getter, 'a', getter);
/******/ return getter;
/******/ };
/******/
/******/ // Object.prototype.hasOwnProperty.call
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "";
/******/
/******/
/******/ // Load entry module and return exports
/******/ return __webpack_require__(__webpack_require__.s = 0);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
// ESM COMPAT FLAG
__webpack_require__.r(__webpack_exports__);
// EXPORTS
__webpack_require__.d(__webpack_exports__, "tsParticles", function() { return /* binding */ tsParticles; });
// CONCATENATED MODULE: ./dist/Classes/Utils/Constants.js
class Constants {}
Constants.canvasClass = "tsparticles-canvas-el";
Constants.randomColorValue = "random";
Constants.touchEndEvent = "touchend";
Constants.mouseUpEvent = "mouseup";
Constants.mouseMoveEvent = "mousemove";
Constants.touchStartEvent = "touchstart";
Constants.touchMoveEvent = "touchmove";
Constants.mouseLeaveEvent = "mouseleave";
Constants.touchCancelEvent = "touchcancel";
Constants.resizeEvent = "resize";
Constants.visibilityChangeEvent = "visibilitychange";
// CONCATENATED MODULE: ./dist/Enums/MoveDirection.js
var MoveDirection;
(function (MoveDirection) {
MoveDirection["bottom"] = "bottom";
MoveDirection["bottomLeft"] = "bottom-left";
MoveDirection["bottomRight"] = "bottom-right";
MoveDirection["left"] = "left";
MoveDirection["none"] = "none";
MoveDirection["right"] = "right";
MoveDirection["top"] = "top";
MoveDirection["topLeft"] = "top-left";
MoveDirection["topRight"] = "top-right";
})(MoveDirection || (MoveDirection = {}));
// CONCATENATED MODULE: ./dist/Classes/Utils/Utils.js
var __awaiter = undefined && undefined.__awaiter || function (thisArg, _arguments, P, generator) {
function adopt(value) {
return value instanceof P ? value : new P(function (resolve) {
resolve(value);
});
}
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) {
try {
step(generator.next(value));
} catch (e) {
reject(e);
}
}
function rejected(value) {
try {
step(generator["throw"](value));
} catch (e) {
reject(e);
}
}
function step(result) {
result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected);
}
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
class Utils_Utils {
static clamp(num, min, max) {
return Math.min(Math.max(num, min), max);
}
static isInArray(value, array) {
return value === array || array.indexOf(value) > -1;
}
static mix(comp1, comp2, weight1, weight2) {
return (comp1 * weight1 + comp2 * weight2) / (weight1 + weight2);
}
static getParticleBaseVelocity(options) {
let velocityBase;
switch (options.particles.move.direction) {
case MoveDirection.top:
velocityBase = {
x: 0,
y: -1
};
break;
case MoveDirection.topRight:
velocityBase = {
x: 0.5,
y: -0.5
};
break;
case MoveDirection.right:
velocityBase = {
x: 1,
y: -0
};
break;
case MoveDirection.bottomRight:
velocityBase = {
x: 0.5,
y: 0.5
};
break;
case MoveDirection.bottom:
velocityBase = {
x: 0,
y: 1
};
break;
case MoveDirection.bottomLeft:
velocityBase = {
x: -0.5,
y: 1
};
break;
case MoveDirection.left:
velocityBase = {
x: -1,
y: 0
};
break;
case MoveDirection.topLeft:
velocityBase = {
x: -0.5,
y: -0.5
};
break;
default:
velocityBase = {
x: 0,
y: 0
};
break;
}
return velocityBase;
}
static getDistanceBetweenCoordinates(pointA, pointB) {
const dx = pointA.x - pointB.x;
const dy = pointA.y - pointB.y;
return Math.sqrt(dx * dx + dy * dy);
}
static loadFont(character) {
return __awaiter(this, void 0, void 0, function* () {
try {
yield document.fonts.load(`${character.weight} 36px '${character.font}'`);
} catch (_a) {}
});
}
static arrayRandomIndex(array) {
return Math.floor(Math.random() * array.length);
}
static itemFromArray(array, index) {
return array[index !== undefined ? index : this.arrayRandomIndex(array)];
}
static randomInRange(min, max) {
return Math.random() * (max - min) + min;
}
static isPointInside(point, size, radius) {
return this.areBoundsInside(this.calculateBounds(point, radius !== null && radius !== void 0 ? radius : 0), size);
}
static areBoundsInside(bounds, size) {
return bounds.left < size.width && bounds.right > 0 && bounds.top < size.height && bounds.bottom > 0;
}
static calculateBounds(point, radius) {
return {
bottom: point.y + radius,
left: point.x - radius,
right: point.x + radius,
top: point.y - radius
};
}
}
// CONCATENATED MODULE: ./dist/Classes/Utils/ShapeUtils.js
class ShapeUtils {
static addShapeDrawer(type, drawer) {
if (!this.drawers[type]) {
this.drawers[type] = drawer;
}
}
static drawShape(context, particle, radius, opacity) {
if (!particle.shape) {
return;
}
const drawer = this.drawers[particle.shape];
if (!drawer) {
return;
}
drawer.draw(context, particle, radius, opacity);
}
}
ShapeUtils.drawers = {};
// CONCATENATED MODULE: ./dist/Classes/Utils/ColorUtils.js
class ColorUtils_ColorUtils {
static colorToRgb(color) {
let res;
if (typeof color.value === "string") {
if (color.value === Constants.randomColorValue) {
res = {
b: Math.floor(Math.random() * 256),
g: Math.floor(Math.random() * 256),
r: Math.floor(Math.random() * 256)
};
} else {
res = ColorUtils_ColorUtils.stringToRgb(color.value);
}
} else {
if (color.value instanceof Array) {
const colorSelected = Utils_Utils.itemFromArray(color.value);
res = ColorUtils_ColorUtils.stringToRgb(colorSelected);
} else {
const rgbColor = color.value;
if (rgbColor.r !== undefined) {
res = rgbColor;
}
const hslColor = color.value;
if (hslColor.h !== undefined) {
res = ColorUtils_ColorUtils.hslToRgb(hslColor);
}
}
}
return res;
}
static stringToAlpha(input) {
var _a;
return (_a = ColorUtils_ColorUtils.stringToRgba(input)) === null || _a === void 0 ? void 0 : _a.a;
}
static stringToRgb(input) {
return ColorUtils_ColorUtils.stringToRgba(input);
}
static hslToRgb(hsl) {
const result = {
b: 0,
g: 0,
r: 0
};
if (hsl.s === 0) {
result.b = hsl.l;
result.g = hsl.l;
result.r = hsl.l;
} else {
const q = hsl.l < 0.5 ? hsl.l * (1 + hsl.s) : hsl.l + hsl.s - hsl.l * hsl.s;
const p = 2 * hsl.l - q;
result.r = ColorUtils_ColorUtils.hue2rgb(p, q, hsl.h + 1 / 3);
result.g = ColorUtils_ColorUtils.hue2rgb(p, q, hsl.h);
result.b = ColorUtils_ColorUtils.hue2rgb(p, q, hsl.h - 1 / 3);
}
result.r = Math.round(result.r * 255);
result.g = Math.round(result.g * 255);
result.b = Math.round(result.b * 255);
return result;
}
static hslaToRgba(hsla) {
const rgbResult = ColorUtils_ColorUtils.hslToRgb(hsla);
return {
a: hsla.a,
b: rgbResult.b,
g: rgbResult.g,
r: rgbResult.r
};
}
static getRandomRgbColor(min) {
var _a;
const fixedMin = min || 0;
const minColor = fixedMin + fixedMin * Math.pow(16, 2) + fixedMin * Math.pow(16, 4);
const maxColor = minColor ^ 0xFFFFFF;
const randomColor = (Math.random() * maxColor + minColor).toString(16);
return (_a = this.stringToRgb(`#${randomColor}`)) !== null && _a !== void 0 ? _a : {
b: 0,
g: 0,
r: 0
};
}
static getStyleFromColor(color, opacity) {
const opacityValue = opacity !== null && opacity !== void 0 ? opacity : 1;
return `rgba(${Math.round(color.r)}, ${Math.round(color.g)}, ${Math.round(color.b)}, ${opacityValue})`;
}
static hue2rgb(p, q, t) {
let tCalc = t;
if (tCalc < 0) {
tCalc += 1;
}
if (tCalc > 1) {
tCalc -= 1;
}
if (tCalc < 1 / 6) {
return p + (q - p) * 6 * tCalc;
}
if (tCalc < 1 / 2) {
return q;
}
if (tCalc < 2 / 3) {
return p + (q - p) * (2 / 3 - tCalc) * 6;
}
return p;
}
static stringToRgba(input) {
if (input.startsWith('rgb')) {
const regex = /rgba?\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(,\s*([\d\.]+)\s*)?\)/i;
const result = regex.exec(input);
return result ? {
a: result.length > 4 ? parseFloat(result[5]) : 1,
b: parseInt(result[3]),
g: parseInt(result[2]),
r: parseInt(result[1])
} : undefined;
} else if (input.startsWith('hsl')) {
const regex = /hsla?\(\s*(\d+)\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(,\s*([\d\.]+)\s*)?\)/i;
const result = regex.exec(input);
return result ? ColorUtils_ColorUtils.hslaToRgba({
a: result.length > 4 ? parseFloat(result[5]) : 1,
h: parseInt(result[1]),
l: parseInt(result[3]),
s: parseInt(result[2])
}) : undefined;
} else {
const shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])([a-f\d])?$/i;
const hexFixed = input.replace(shorthandRegex, (_m, r, g, b, a) => {
return r + r + g + g + b + b + (a ? a + a : "");
});
const regex = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})?$/i;
const result = regex.exec(hexFixed);
return result ? {
a: parseInt(result[4], 16) / 0xFF,
b: parseInt(result[3], 16),
g: parseInt(result[2], 16),
r: parseInt(result[1], 16)
} : undefined;
}
}
}
// CONCATENATED MODULE: ./dist/Classes/Utils/CanvasUtils.js
class CanvasUtils_CanvasUtils {
static paintBase(context, dimension, baseColor) {
context.save();
context.fillStyle = baseColor !== null && baseColor !== void 0 ? baseColor : "rgba(0,0,0,0)";
context.fillRect(0, 0, dimension.width, dimension.height);
context.restore();
}
static clear(context, dimension) {
context.clearRect(0, 0, dimension.width, dimension.height);
}
static drawPolygonMask(context, rawData, stroke) {
const color = typeof stroke.color === "string" ? ColorUtils_ColorUtils.stringToRgb(stroke.color) : ColorUtils_ColorUtils.colorToRgb(stroke.color);
if (color) {
context.save();
context.beginPath();
context.moveTo(rawData[0].x, rawData[0].y);
for (let i = 1; i < rawData.length; i++) {
context.lineTo(rawData[i].x, rawData[i].y);
}
context.closePath();
context.strokeStyle = ColorUtils_ColorUtils.getStyleFromColor(color);
context.lineWidth = stroke.width;
context.stroke();
context.restore();
}
}
static drawPolygonMaskPath(context, path, stroke, position) {
context.save();
context.translate(position.x, position.y);
const color = typeof stroke.color === "string" ? ColorUtils_ColorUtils.stringToRgb(stroke.color) : ColorUtils_ColorUtils.colorToRgb(stroke.color);
if (color) {
context.strokeStyle = ColorUtils_ColorUtils.getStyleFromColor(color, stroke.opacity);
context.lineWidth = stroke.width;
context.stroke(path);
}
context.restore();
}
static drawLineLinked(context, width, begin, end, backgroundMask, colorLine, opacity, shadow) {
context.save();
if (backgroundMask) {
context.globalCompositeOperation = 'destination-out';
}
if (colorLine) {
context.strokeStyle = ColorUtils_ColorUtils.getStyleFromColor(colorLine, opacity);
;
}
context.lineWidth = width;
context.beginPath();
const color = typeof shadow.color === "string" ? ColorUtils_ColorUtils.stringToRgb(shadow.color) : ColorUtils_ColorUtils.colorToRgb(shadow.color);
if (shadow.enable && color) {
context.shadowBlur = shadow.blur;
context.shadowColor = ColorUtils_ColorUtils.getStyleFromColor(color);
}
context.moveTo(begin.x, begin.y);
context.lineTo(end.x, end.y);
context.stroke();
context.closePath();
context.restore();
}
static drawConnectLine(context, width, lineStyle, begin, end) {
context.save();
context.beginPath();
context.lineWidth = width;
context.strokeStyle = lineStyle;
context.moveTo(begin.x, begin.y);
context.lineTo(end.x, end.y);
context.stroke();
context.closePath();
context.restore();
}
static gradient(context, p1, p2, midColor, opacity) {
const gradStop = Math.floor(p2.radius / p1.radius);
if (!p1.color || !p2.color) {
return;
}
const sourcePos = p1.position;
const destPos = p2.position;
const grad = context.createLinearGradient(sourcePos.x, sourcePos.y, destPos.x, destPos.y);
grad.addColorStop(0, ColorUtils_ColorUtils.getStyleFromColor(p1.color, opacity));
grad.addColorStop(gradStop > 1 ? 1 : gradStop, ColorUtils_ColorUtils.getStyleFromColor(midColor, opacity));
grad.addColorStop(1, ColorUtils_ColorUtils.getStyleFromColor(p2.color, opacity));
return grad;
}
static drawGrabLine(context, width, begin, end, colorLine, opacity) {
context.save();
context.strokeStyle = ColorUtils_ColorUtils.getStyleFromColor(colorLine, opacity);
context.lineWidth = width;
context.beginPath();
context.moveTo(begin.x, begin.y);
context.lineTo(end.x, end.y);
context.stroke();
context.closePath();
context.restore();
}
static drawParticle(context, particle, colorValue, backgroundMask, radius, opacity) {
context.save();
const shadow = particle.container.options.particles.shadow;
const shadowColor = particle.shadowColor;
if (shadow.enable && shadowColor) {
context.shadowBlur = shadow.blur;
context.shadowColor = ColorUtils_ColorUtils.getStyleFromColor(shadowColor);
context.shadowOffsetX = shadow.offset.x;
context.shadowOffsetY = shadow.offset.y;
}
context.fillStyle = colorValue;
const pos = {
x: particle.position.x + particle.offset.x,
y: particle.position.y + particle.offset.y
};
context.translate(pos.x, pos.y);
context.beginPath();
if (particle.angle !== 0) {
context.rotate(particle.angle * Math.PI / 180);
}
if (backgroundMask) {
context.globalCompositeOperation = "destination-out";
}
const stroke = particle.stroke;
if (stroke.width > 0 && particle.strokeColor) {
context.strokeStyle = ColorUtils_ColorUtils.getStyleFromColor(particle.strokeColor, particle.stroke.opacity);
context.lineWidth = stroke.width;
}
ShapeUtils.drawShape(context, particle, radius, opacity);
if (particle.close) {
context.closePath();
}
if (stroke.width > 0 && particle.strokeColor) {
context.stroke();
}
if (particle.fill) {
context.fill();
}
context.restore();
}
}
// CONCATENATED MODULE: ./dist/Classes/Canvas.js
class Canvas_Canvas {
constructor(container) {
this.container = container;
this.dimension = {
height: 0,
width: 0
};
this.context = null;
this.generatedCanvas = false;
}
init() {
this.size();
const container = this.container;
const options = container.options;
const cover = options.backgroundMask.cover;
const trail = options.particles.move.trail;
this.coverColor = ColorUtils_ColorUtils.colorToRgb(cover.color !== undefined ? cover.color : options.backgroundMask.cover);
this.trailFillColor = typeof trail.fillColor === "string" ? ColorUtils_ColorUtils.stringToRgb(trail.fillColor) : ColorUtils_ColorUtils.colorToRgb(trail.fillColor);
this.paint();
}
loadCanvas(canvas, generatedCanvas) {
var _a;
if (!canvas.className) {
canvas.className = Constants.canvasClass;
}
if (this.generatedCanvas) {
(_a = this.element) === null || _a === void 0 ? void 0 : _a.remove();
}
this.generatedCanvas = generatedCanvas !== null && generatedCanvas !== void 0 ? generatedCanvas : false;
this.element = canvas;
this.dimension.height = canvas.offsetHeight;
this.dimension.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();
}
if (this.context) {
CanvasUtils_CanvasUtils.clear(this.context, this.dimension);
}
}
size() {
if (this.element) {
this.element.width = this.dimension.width;
this.element.height = this.dimension.height;
}
}
paint() {
const container = this.container;
const options = container.options;
if (this.context) {
if (options.backgroundMask.enable && options.backgroundMask.cover) {
if (this.coverColor) {
this.paintBase(ColorUtils_ColorUtils.getStyleFromColor(this.coverColor));
} else {
this.paintBase();
}
} else {
this.paintBase();
}
}
}
clear() {
const container = this.container;
const options = container.options;
const trail = options.particles.move.trail;
if (options.backgroundMask.enable) {
this.paint();
} else if (trail.enable && trail.length > 0 && this.trailFillColor) {
this.paintBase(ColorUtils_ColorUtils.getStyleFromColor(this.trailFillColor, 1 / trail.length));
} else if (this.context) {
CanvasUtils_CanvasUtils.clear(this.context, this.dimension);
}
}
isPointInPath(path, point) {
var _a, _b;
return (_b = (_a = this.context) === null || _a === void 0 ? void 0 : _a.isPointInPath(path, point.x, point.y)) !== null && _b !== void 0 ? _b : false;
}
drawPolygonMask() {
const container = this.container;
const options = container.options;
const context = this.context;
const polygonDraw = options.polygon.draw;
const polygon = container.polygon;
const rawData = polygon.raw;
const path = polygon.polygonPath;
const path2dSupported = polygon.path2DSupported;
if (context) {
if (path2dSupported && path && polygon.offset) {
CanvasUtils_CanvasUtils.drawPolygonMaskPath(context, path, polygonDraw.stroke, polygon.offset);
} else if (rawData) {
CanvasUtils_CanvasUtils.drawPolygonMask(context, rawData, polygonDraw.stroke);
}
}
}
drawLinkedLine(p1, p2, pos1, pos2, opacity) {
const container = this.container;
const options = container.options;
const ctx = this.context;
if (!ctx) {
return;
}
let colorLine;
if (container.particles.lineLinkedColor === Constants.randomColorValue) {
colorLine = ColorUtils_ColorUtils.getRandomRgbColor();
} else if (container.particles.lineLinkedColor == "mid" && p1.color && p2.color) {
const sourceColor = p1.color;
const destColor = p2.color;
colorLine = {
b: Math.floor(Utils_Utils.mix(sourceColor.b, destColor.b, p1.radius, p2.radius)),
g: Math.floor(Utils_Utils.mix(sourceColor.g, destColor.g, p1.radius, p2.radius)),
r: Math.floor(Utils_Utils.mix(sourceColor.r, destColor.r, p1.radius, p2.radius))
};
} else {
colorLine = container.particles.lineLinkedColor;
}
const width = container.retina.lineLinkedWidth;
CanvasUtils_CanvasUtils.drawLineLinked(ctx, width, pos1, pos2, options.backgroundMask.enable, colorLine, opacity, options.particles.lineLinked.shadow);
}
drawConnectLine(p1, p2) {
const lineStyle = this.lineStyle(p1, p2);
if (!lineStyle) {
return;
}
const ctx = this.context;
if (!ctx) {
return;
}
CanvasUtils_CanvasUtils.drawConnectLine(ctx, this.container.retina.lineLinkedWidth, lineStyle, p1.position, p2.position);
}
drawGrabLine(particle, opacity, mousePos) {
const container = this.container;
const options = container.options;
const optColor = options.particles.lineLinked.color;
let lineColor = container.particles.lineLinkedColor || (typeof optColor === "string" ? ColorUtils_ColorUtils.stringToRgb(optColor) : ColorUtils_ColorUtils.colorToRgb(optColor));
if (lineColor == Constants.randomColorValue) {
lineColor = ColorUtils_ColorUtils.getRandomRgbColor();
}
container.particles.lineLinkedColor = lineColor;
let colorLine = {
r: 127,
g: 127,
b: 127
};
const ctx = container.canvas.context;
if (!ctx) {
return;
}
if (container.particles.lineLinkedColor == Constants.randomColorValue) {
colorLine = ColorUtils_ColorUtils.getRandomRgbColor() || colorLine;
} else {
colorLine = container.particles.lineLinkedColor || colorLine;
}
const beginPos = {
x: particle.position.x + particle.offset.x,
y: particle.position.y + particle.offset.y
};
CanvasUtils_CanvasUtils.drawGrabLine(ctx, container.retina.lineLinkedWidth, beginPos, mousePos, colorLine, opacity);
}
drawParticle(particle) {
const container = this.container;
const options = container.options;
let colorValue;
const radius = particle.bubbler.radius !== undefined ? particle.bubbler.radius : particle.radius;
const opacity = particle.bubbler.opacity !== undefined ? particle.bubbler.opacity : particle.opacity.value;
if (particle.color) {
colorValue = ColorUtils_ColorUtils.getStyleFromColor(particle.color, opacity);
}
if (!this.context || !colorValue) {
return;
}
CanvasUtils_CanvasUtils.drawParticle(this.context, particle, colorValue, options.backgroundMask.enable, radius, opacity);
}
paintBase(baseColor) {
if (this.context) {
CanvasUtils_CanvasUtils.paintBase(this.context, this.dimension, baseColor);
}
}
lineStyle(p1, p2) {
const container = this.container;
const options = container.options;
const connectOptions = options.interactivity.modes.connect;
if (p1.color && p2.color) {
const sourceRgb = p1.color;
const destRgb = p2.color;
const midRgb = {
b: Utils_Utils.mix(sourceRgb.b, destRgb.b, p1.radius, p2.radius),
g: Utils_Utils.mix(sourceRgb.g, destRgb.g, p1.radius, p2.radius),
r: Utils_Utils.mix(sourceRgb.r, destRgb.r, p1.radius, p2.radius)
};
if (this.context) {
return CanvasUtils_CanvasUtils.gradient(this.context, p1, p2, midRgb, connectOptions.lineLinked.opacity);
}
}
}
initBackground() {
const container = this.container;
const options = container.options;
const background = options.background;
const element = this.element;
if (!element) {
return;
}
const elementStyle = element.style;
if (background.color) {
const color = typeof background.color === "string" ? ColorUtils_ColorUtils.stringToRgb(background.color) : ColorUtils_ColorUtils.colorToRgb(background.color);
if (color) {
elementStyle.backgroundColor = ColorUtils_ColorUtils.getStyleFromColor(color, background.opacity);
}
}
if (background.image) {
elementStyle.backgroundImage = background.image;
}
if (background.position) {
elementStyle.backgroundPosition = background.position;
}
if (background.repeat) {
elementStyle.backgroundRepeat = background.repeat;
}
if (background.size) {
elementStyle.backgroundSize = background.size;
}
}
}
// CONCATENATED MODULE: ./dist/Enums/Modes/ClickMode.js
var ClickMode;
(function (ClickMode) {
ClickMode["bubble"] = "bubble";
ClickMode["push"] = "push";
ClickMode["remove"] = "remove";
ClickMode["repulse"] = "repulse";
})(ClickMode || (ClickMode = {}));
// CONCATENATED MODULE: ./dist/Enums/InteractivityDetect.js
var InteractivityDetect;
(function (InteractivityDetect) {
InteractivityDetect["canvas"] = "canvas";
InteractivityDetect["parent"] = "parent";
InteractivityDetect["window"] = "window";
})(InteractivityDetect || (InteractivityDetect = {}));
// CONCATENATED MODULE: ./dist/Enums/PolygonMaskType.js
var PolygonMaskType;
(function (PolygonMaskType) {
PolygonMaskType["inline"] = "inline";
PolygonMaskType["inside"] = "inside";
PolygonMaskType["outside"] = "outside";
PolygonMaskType["none"] = "none";
})(PolygonMaskType || (PolygonMaskType = {}));
// CONCATENATED MODULE: ./dist/Classes/Utils/EventListeners.js
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.visibilityChangeHandler = () => this.handleVisibilityChange();
this.resizeHandler = () => this.handleWindowResize();
}
addListeners() {
this.manageListeners(true);
}
removeListeners() {
this.manageListeners(false);
}
manageListeners(add) {
const container = this.container;
const options = container.options;
if (options.interactivity.detectsOn === InteractivityDetect.window) {
container.interactivity.element = window;
} else if (options.interactivity.detectsOn === InteractivityDetect.parent && container.canvas.element) {
container.interactivity.element = container.canvas.element.parentNode;
} else {
container.interactivity.element = container.canvas.element;
}
const interactivityEl = container.interactivity.element;
if (interactivityEl && (options.interactivity.events.onHover.enable || options.interactivity.events.onClick.enable)) {
this.manageListener(interactivityEl, Constants.mouseMoveEvent, this.mouseMoveHandler, add);
this.manageListener(interactivityEl, Constants.touchStartEvent, this.touchStartHandler, add);
this.manageListener(interactivityEl, Constants.touchMoveEvent, this.touchMoveHandler, add);
if (!options.interactivity.events.onClick.enable) {
this.manageListener(interactivityEl, Constants.touchEndEvent, this.touchEndHandler, add);
}
this.manageListener(interactivityEl, Constants.mouseLeaveEvent, this.mouseLeaveHandler, add);
this.manageListener(interactivityEl, Constants.touchCancelEvent, this.touchCancelHandler, add);
}
if (options.interactivity.events.onClick.enable && interactivityEl) {
this.manageListener(interactivityEl, Constants.touchEndEvent, this.touchEndClickHandler, add);
this.manageListener(interactivityEl, Constants.mouseUpEvent, this.mouseUpHandler, add);
}
if (options.interactivity.events.resize) {
this.manageListener(window, Constants.resizeEvent, this.resizeHandler, add);
}
if (document) {
this.manageListener(document, Constants.visibilityChangeEvent, this.visibilityChangeHandler, add, false);
}
}
manageListener(element, event, handler, add, options) {
if (add) {
this.addListener(element, event, handler, options);
} else {
this.removeListener(element, event, handler, options);
}
}
addListener(element, event, handler, options) {
element.addEventListener(event, handler, options);
}
removeListener(element, event, handler, options) {
element.removeEventListener(event, handler, options);
}
handleWindowResize() {
const container = this.container;
const options = container.options;
if (!container.canvas.element) {
return;
}
container.canvas.dimension.width = container.canvas.element.offsetWidth;
container.canvas.dimension.height = container.canvas.element.offsetHeight;
if (container.retina.isRetina) {
container.canvas.dimension.width *= container.retina.pxRatio;
container.canvas.dimension.height *= container.retina.pxRatio;
}
container.canvas.element.width = container.canvas.dimension.width;
container.canvas.element.height = container.canvas.dimension.height;
if (!options.particles.move.enable) {
container.particles.redraw();
}
container.densityAutoParticles();
container.polygon.redraw();
}
handleVisibilityChange() {
const container = this.container;
const options = container.options;
if (!options.pauseOnBlur) {
return;
}
if (document === null || document === void 0 ? void 0 : document.hidden) {
container.pageHidden = true;
container.pause();
} else {
container.pageHidden = false;
container.play();
}
}
mouseTouchMove(e) {
var _a, _b, _c;
const container = this.container;
const options = container.options;
let pos;
if (e.type.startsWith("mouse")) {
this.canPush = true;
const mouseEvent = e;
if (container.interactivity.element === window && container.canvas.element) {
const clientRect = container.canvas.element.getBoundingClientRect();
pos = {
x: mouseEvent.clientX - clientRect.left,
y: mouseEvent.clientY - clientRect.top
};
} else if (options.interactivity.detectsOn === InteractivityDetect.parent) {
const source = mouseEvent.target;
const target = mouseEvent.currentTarget;
if (source && target) {
const sourceRect = source.getBoundingClientRect();
const targetRect = target.getBoundingClientRect();
pos = {
x: mouseEvent.offsetX + sourceRect.left - targetRect.left,
y: mouseEvent.offsetY + sourceRect.top - targetRect.top
};
} else {
pos = {
x: mouseEvent.offsetX || mouseEvent.clientX,
y: mouseEvent.offsetY || mouseEvent.clientY
};
}
} else {
pos = {
x: mouseEvent.offsetX || mouseEvent.clientX,
y: mouseEvent.offsetY || mouseEvent.clientY
};
}
} else {
this.canPush = e.type !== "touchmove";
const touchEvent = e;
const lastTouch = touchEvent.touches[touchEvent.touches.length - 1];
const canvasRect = (_a = container.canvas.element) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect();
pos = {
x: lastTouch.clientX - ((_b = canvasRect === null || canvasRect === void 0 ? void 0 : canvasRect.left) !== null && _b !== void 0 ? _b : 0),
y: lastTouch.clientY - ((_c = canvasRect === null || canvasRect === void 0 ? void 0 : canvasRect.top) !== null && _c !== void 0 ? _c : 0)
};
}
container.interactivity.mouse.position = pos;
if (container.retina.isRetina) {
container.interactivity.mouse.position.x *= container.retina.pxRatio;
container.interactivity.mouse.position.y *= container.retina.pxRatio;
}
container.interactivity.status = Constants.mouseMoveEvent;
}
mouseTouchFinish() {
const container = this.container;
delete container.interactivity.mouse.position;
container.interactivity.status = Constants.mouseLeaveEvent;
}
mouseTouchClick(e) {
const container = this.container;
const options = container.options;
if (options.polygon.enable && options.polygon.type !== PolygonMaskType.none && options.polygon.type !== PolygonMaskType.inline) {
if (container.polygon.checkInsidePolygon(container.interactivity.mouse.position)) {
this.doMouseTouchClick(e);
}
} else {
this.doMouseTouchClick(e);
}
}
doMouseTouchClick(e) {
const container = this.container;
const options = container.options;
if (this.canPush) {
if (container.interactivity.mouse.position) {
container.interactivity.mouse.clickPosition = {
x: container.interactivity.mouse.position.x,
y: container.interactivity.mouse.position.y
};
}
container.interactivity.mouse.clickTime = new Date().getTime();
const pushNb = options.interactivity.modes.push.quantity;
const removeNb = options.interactivity.modes.remove.quantity;
switch (options.interactivity.events.onClick.mode) {
case ClickMode.push:
if (options.particles.move.enable) {
container.particles.push(pushNb, container.interactivity.mouse);
} else {
if (options.interactivity.modes.push.quantity === 1) {
container.particles.push(pushNb, container.interactivity.mouse);
} else if (options.interactivity.modes.push.quantity > 1) {
container.particles.push(pushNb);
}
}
break;
case ClickMode.remove:
container.particles.removeQuantity(removeNb);
break;
case ClickMode.bubble:
container.bubble.clicking = true;
break;
case ClickMode.repulse:
container.repulse.clicking = true;
container.repulse.count = 0;
container.repulse.finish = false;
setTimeout(() => {
if (!container.destroyed) {
container.repulse.clicking = false;
}
}, options.interactivity.modes.repulse.duration * 1000);
break;
}
}
e.preventDefault();
if (e.type === "touchend") {
setTimeout(() => this.mouseTouchFinish(), 500);
}
e.preventDefault();
}
}
// CONCATENATED MODULE: ./dist/Enums/ProcessBubbleType.js
var ProcessBubbleType;
(function (ProcessBubbleType) {
ProcessBubbleType["opacity"] = "opacity";
ProcessBubbleType["size"] = "size";
})(ProcessBubbleType || (ProcessBubbleType = {}));
// CONCATENATED MODULE: ./dist/Enums/Modes/HoverMode.js
var HoverMode;
(function (HoverMode) {
HoverMode["bubble"] = "bubble";
HoverMode["connect"] = "connect";
HoverMode["grab"] = "grab";
HoverMode["repulse"] = "repulse";
HoverMode["slow"] = "slow";
})(HoverMode || (HoverMode = {}));
// CONCATENATED MODULE: ./dist/Classes/Particle/Bubbler.js
class Bubbler_Bubbler {
constructor(container, particle) {
this.container = container;
this.particle = particle;
}
bubble() {
const container = this.container;
const options = container.options;
const hoverEnabled = options.interactivity.events.onHover.enable;
const hoverMode = options.interactivity.events.onHover.mode;
const clickEnabled = options.interactivity.events.onClick.enable;
const clickMode = options.interactivity.events.onClick.mode;
if (hoverEnabled && Utils_Utils.isInArray(HoverMode.bubble, hoverMode)) {
this.hoverBubble();
} else if (clickEnabled && Utils_Utils.isInArray(ClickMode.bubble, clickMode)) {
this.clickBubble();
}
}
init() {
const particle = this.particle;
this.opacity = particle.opacity.value;
this.radius = particle.radius;
}
process(distMouse, timeSpent, data) {
const container = this.container;
const options = container.options;
const bubbleDuration = options.interactivity.modes.bubble.duration;
const bubbleParam = data.bubbleObj.optValue;
const bubbleDistance = container.retina.bubbleModeDistance;
const particlesParam = data.particlesObj.optValue;
const pObjBubble = data.bubbleObj.value;
const pObj = data.particlesObj.value || 0;
const type = data.type;
if (bubbleParam !== particlesParam) {
if (!container.bubble.durationEnd) {
if (distMouse <= bubbleDistance) {
const obj = pObjBubble !== null && pObjBubble !== void 0 ? pObjBubble : pObj;
if (obj !== bubbleParam) {
const value = pObj - timeSpent * (pObj - bubbleParam) / bubbleDuration;
if (type === ProcessBubbleType.size) {
this.radius = value;
}
if (type === ProcessBubbleType.opacity) {
this.opacity = value;
}
}
} else {
if (type === ProcessBubbleType.size) {
this.radius = undefined;
}
if (type === ProcessBubbleType.opacity) {
this.opacity = undefined;
}
}
} else if (pObjBubble) {
const value = bubbleParam * 2 - pObj - timeSpent * (pObj - bubbleParam) / bubbleDuration;
if (type === ProcessBubbleType.size) {
this.radius = value;
}
if (type === ProcessBubbleType.opacity) {
this.opacity = value;
}
}
}
}
clickBubble() {
const container = this.container;
const options = container.options;
const particle = this.particle;
const mouseClickPos = container.interactivity.mouse.clickPosition || {
x: 0,
y: 0
};
const distMouse = Utils_Utils.getDistanceBetweenCoordinates(particle.position, mouseClickPos);
const timeSpent = (new Date().getTime() - (container.interactivity.mouse.clickTime || 0)) / 1000;
if (container.bubble.clicking) {
if (timeSpent > options.interactivity.modes.bubble.duration) {
container.bubble.durationEnd = true;
}
if (timeSpent > options.interactivity.modes.bubble.duration * 2) {
container.bubble.clicking = false;
container.bubble.durationEnd = false;
}
const sizeData = {
bubbleObj: {
optValue: container.retina.bubbleModeSize,
value: this.radius
},
particlesObj: {
optValue: container.retina.sizeValue,
value: this.particle.radius
},
type: ProcessBubbleType.size
};
this.process(distMouse, timeSpent, sizeData);
const opacityData = {
bubbleObj: {
optValue: options.interactivity.modes.bubble.opacity,
value: this.opacity
},
particlesObj: {
optValue: options.particles.opacity.value,
value: this.particle.opacity.value
},
type: ProcessBubbleType.opacity
};
this.process(distMouse, timeSpent, opacityData);
}
}
hoverBubble() {
const container = this.container;
const particle = this.particle;
const mousePos = container.interactivity.mouse.position || {
x: 0,
y: 0
};
const distMouse = Utils_Utils.getDistanceBetweenCoordinates(particle.position, mousePos);
const ratio = 1 - distMouse / container.retina.bubbleModeDistance;
if (distMouse <= container.retina.bubbleModeDistance) {
if (ratio >= 0 && container.interactivity.status === Constants.mouseMoveEvent) {
this.hoverBubbleSize(ratio);
this.hoverBubbleOpacity(ratio);
}
} else {
this.init();
}
if (container.interactivity.status === Constants.mouseLeaveEvent) {
this.init();
}
}
hoverBubbleSize(ratio) {
const container = this.container;
const options = container.options;
const particle = this.particle;
const modeSize = options.interactivity.modes.bubble.size;
const optSize = options.particles.size.value;
const pSize = particle.radius;
if (container.retina.bubbleModeSize > container.retina.sizeValue) {
const size = pSize + modeSize * ratio;
if (size > pSize && size <= modeSize) {
this.radius = size;
}
} else if (container.retina.bubbleModeSize < container.retina.sizeValue) {
const size = pSize - (optSize - modeSize) * ratio;
if (size < pSize && size >= modeSize) {
this.radius = size;
}
}
}
hoverBubbleOpacity(ratio) {
const container = this.container;
const options = container.options;
const particle = this.particle;
const modeOpacity = options.interactivity.modes.bubble.opacity;
const optOpacity = options.particles.opacity.value;
const pOpacity = particle.opacity.value;
if (modeOpacity > optOpacity) {
const opacity = pOpacity + modeOpacity * ratio;
if (opacity > pOpacity && opacity <= modeOpacity) {
this.opacity = opacity;
}
} else if (modeOpacity < optOpacity) {
const opacity = pOpacity - (optOpacity - modeOpacity) * ratio;
if (opacity < pOpacity && opacity >= modeOpacity) {
this.opacity = opacity;
}
}
}
}
// CONCATENATED MODULE: ./dist/Classes/Particle/Drawer.js
class Drawer {
constructor(container, particle) {
this.container = container;
this.particle = particle;
}
draw() {
const container = this.container;
const particle = this.particle;
container.canvas.drawParticle(particle);
}
}
// CONCATENATED MODULE: ./dist/Classes/Particle/Grabber.js
class Grabber_Grabber {
constructor(container, particle) {
this.container = container;
this.particle = particle;
}
grab() {
const container = this.container;
const options = container.options;
const particle = this.particle;
const interactivity = options.interactivity;
if (interactivity.events.onHover.enable && container.interactivity.status === Constants.mouseMoveEvent) {
const mousePos = container.interactivity.mouse.position || {
x: 0,
y: 0
};
const distMouse = Utils_Utils.getDistanceBetweenCoordinates(particle.position, mousePos);
if (distMouse <= container.retina.grabModeDistance) {
const lineOpacity = interactivity.modes.grab.lineLinked.opacity;
const grabDistance = container.retina.grabModeDistance;
const opacityLine = lineOpacity - distMouse * lineOpacity / grabDistance;
if (opacityLine > 0) {
container.canvas.drawGrabLine(particle, opacityLine, mousePos);
}
}
}
}
}
// CONCATENATED MODULE: ./dist/Enums/OutMode.js
var OutMode;
(function (OutMode) {
OutMode["bounce"] = "bounce";
OutMode["bounceHorizontal"] = "bounce-horizontal";
OutMode["bounceVertical"] = "bounce-vertical";
OutMode["out"] = "out";
OutMode["destroy"] = "destroy";
})(OutMode || (OutMode = {}));
// CONCATENATED MODULE: ./dist/Enums/Modes/DivMode.js
var DivMode;
(function (DivMode) {
DivMode["repulse"] = "repulse";
})(DivMode || (DivMode = {}));
// CONCATENATED MODULE: ./dist/Classes/Particle/Repulser.js
class Repulser_Repulser {
constructor(container, particle) {
this.container = container;
this.particle = particle;
}
repulse() {
const container = this.container;
const options = container.options;
const hoverEnabled = options.interactivity.events.onHover.enable;
const clickEnabled = options.interactivity.events.onClick.enable;
const mouseMoveStatus = container.interactivity.status === Constants.mouseMoveEvent;
const hoverMode = options.interactivity.events.onHover.mode;
const clickMode = options.interactivity.events.onClick.mode;
const divMode = options.interactivity.events.onDiv.mode;
if (mouseMoveStatus && hoverEnabled && Utils_Utils.isInArray(HoverMode.repulse, hoverMode)) {
this.hoverRepulse();
} else if (clickEnabled && Utils_Utils.isInArray(ClickMode.repulse, clickMode)) {
this.clickRepulse();
} else if (options.interactivity.events.onDiv.enable && Utils_Utils.isInArray(DivMode.repulse, divMode)) {
this.divRepulse();
}
}
divRepulse() {
const container = this.container;
const options = container.options;
const particle = this.particle;
const elem = document.getElementById(options.interactivity.events.onDiv.elementId);
const pos = {
x: elem.offsetLeft + elem.offsetWidth / 2,
y: elem.offsetTop + elem.offsetHeight / 2
};
let divWidth = elem.offsetWidth / 2;
if (container.retina.isRetina) {
pos.x *= container.retina.pxRatio;
pos.y *= container.retina.pxRatio;
divWidth *= container.retina.pxRatio;
}
const dxDiv = particle.position.x - pos.x;
const dyDiv = particle.position.y - pos.y;
const distDiv = Math.sqrt(dxDiv * dxDiv + dyDiv * dyDiv);
const normVec = {
x: dxDiv / distDiv,
y: dyDiv / distDiv
};
const repulseRadius = divWidth;
const velocity = 100;
const repulseFactor = Utils_Utils.clamp((-Math.pow(distDiv / repulseRadius, 4) + 1) * velocity, 0, 50);
this.particle.position.x += normVec.x * repulseFactor;
this.particle.position.y += normVec.y * repulseFactor;
}
clickRepulse() {
const container = this.container;
const particle = this.particle;
if (!container.repulse.finish) {
if (!container.repulse.count) {
container.repulse.count = 0;
}
container.repulse.count++;
if (container.repulse.count === container.particles.count) {
container.repulse.finish = true;
}
}
if (container.repulse.clicking) {
const repulseDistance = container.retina.repulseModeDistance;
const repulseRadius = Math.pow(repulseDistance / 6, 3);
const mouseClickPos = container.interactivity.mouse.clickPosition || {
x: 0,
y: 0
};
const dx = mouseClickPos.x - particle.position.x;
const dy = mouseClickPos.y - particle.position.y;
const d = dx * dx + dy * dy;
const force = -repulseRadius / d;
if (d <= repulseRadius) {
this.processRepulse(dx, dy, force);
}
} else if (container.repulse.clicking === false) {
particle.velocity.horizontal = particle.initialVelocity.horizontal;
particle.velocity.vertical = particle.initialVelocity.vertical;
}
}
hoverRepulse() {
const container = this.container;
const options = container.options;
const particle = this.particle;
const mousePos = container.interactivity.mouse.position || {
x: 0,
y: 0
};
const dxMouse = particle.position.x - mousePos.x;
const dyMouse = particle.position.y - mousePos.y;
const distMouse = Math.sqrt(dxMouse * dxMouse + dyMouse * dyMouse);
const normVec = {
x: dxMouse / distMouse,
y: dyMouse / distMouse
};
const repulseRadius = container.retina.repulseModeDistance;
const velocity = 100;
const repulseFactor = Utils_Utils.clamp((1 - Math.pow(distMouse / repulseRadius, 2)) * velocity, 0, 50);
const pos = {
x: particle.position.x + normVec.x * repulseFactor,