UNPKG

tsparticles

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.

315 lines (314 loc) 12.1 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.Utils = void 0; const OutModeDirection_1 = require("../Enums/Directions/OutModeDirection"); const NumberUtils_1 = require("./NumberUtils"); function rectSideBounce(pSide, pOtherSide, rectSide, rectOtherSide, velocity, factor) { const res = { bounced: false }; if (pOtherSide.min >= rectOtherSide.min && pOtherSide.min <= rectOtherSide.max && pOtherSide.max >= rectOtherSide.min && pOtherSide.max <= rectOtherSide.max) { 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) { if (selectors instanceof Array) { for (const selector of selectors) { if (element.matches(selector)) { return true; } } return false; } else { return element.matches(selectors); } } class Utils { static isSsr() { return typeof window === "undefined" || !window; } static get animate() { return Utils.isSsr() ? (callback) => setTimeout(callback) : (callback) => (window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || window.setTimeout)(callback); } static get cancelAnimation() { return Utils.isSsr() ? (handle) => clearTimeout(handle) : (handle) => (window.cancelAnimationFrame || window.webkitCancelRequestAnimationFrame || window.mozCancelRequestAnimationFrame || window.oCancelRequestAnimationFrame || window.msCancelRequestAnimationFrame || window.clearTimeout)(handle); } static isInArray(value, array) { return value === array || (array instanceof Array && array.indexOf(value) > -1); } 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, useIndex = true) { const fixedIndex = index !== undefined && useIndex ? index % array.length : Utils.arrayRandomIndex(array); return array[fixedIndex]; } static isPointInside(point, size, radius, direction) { return Utils.areBoundsInside(Utils.calculateBounds(point, radius !== null && radius !== void 0 ? radius : 0), size, direction); } static areBoundsInside(bounds, size, direction) { let inside = true; if (!direction || direction === OutModeDirection_1.OutModeDirection.bottom) { inside = bounds.top < size.height; } if (inside && (!direction || direction === OutModeDirection_1.OutModeDirection.left)) { inside = bounds.right > 0; } if (inside && (!direction || direction === OutModeDirection_1.OutModeDirection.right)) { inside = bounds.left < size.width; } if (inside && (!direction || direction === OutModeDirection_1.OutModeDirection.top)) { inside = bounds.bottom > 0; } return inside; } static calculateBounds(point, radius) { return { bottom: point.y + radius, left: point.x - radius, right: point.x + radius, top: point.y - radius, }; } static loadImage(source) { return new Promise((resolve, reject) => { if (!source) { reject("Error tsParticles - No image.src"); return; } const image = { source: source, type: source.substr(source.length - 3), }; const img = new Image(); img.addEventListener("load", () => { image.element = img; resolve(image); }); img.addEventListener("error", () => { reject(`Error tsParticles - loading image: ${source}`); }); img.src = source; }); } static downloadSvgImage(source) { return __awaiter(this, void 0, void 0, function* () { if (!source) { throw new Error("Error tsParticles - No image.src"); } const image = { source: source, type: source.substr(source.length - 3), }; if (image.type !== "svg") { return Utils.loadImage(source); } const response = yield fetch(image.source); if (!response.ok) { throw new Error("Error tsParticles - Image not found"); } image.svgData = yield response.text(); return image; }); } static deepExtend(destination, ...sources) { for (const source of sources) { if (source === undefined || source === null) { continue; } if (typeof source !== "object") { destination = source; continue; } const sourceIsArray = Array.isArray(source); if (sourceIsArray && (typeof destination !== "object" || !destination || !Array.isArray(destination))) { destination = []; } else if (!sourceIsArray && (typeof destination !== "object" || !destination || Array.isArray(destination))) { destination = {}; } for (const key in source) { if (key === "__proto__") { continue; } const sourceDict = source; const value = sourceDict[key]; const isObject = typeof value === "object"; const destDict = destination; destDict[key] = isObject && Array.isArray(value) ? value.map((v) => Utils.deepExtend(destDict[key], v)) : Utils.deepExtend(destDict[key], value); } } return destination; } static isDivModeEnabled(mode, divs) { return divs instanceof Array ? !!divs.find((t) => t.enable && Utils.isInArray(mode, t.mode)) : Utils.isInArray(mode, divs.mode); } static divModeExecute(mode, divs, callback) { if (divs instanceof Array) { for (const div of divs) { const divMode = div.mode; const divEnabled = div.enable; if (divEnabled && Utils.isInArray(mode, divMode)) { Utils.singleDivModeExecute(div, callback); } } } else { const divMode = divs.mode; const divEnabled = divs.enable; if (divEnabled && Utils.isInArray(mode, divMode)) { Utils.singleDivModeExecute(divs, callback); } } } static singleDivModeExecute(div, callback) { const selectors = div.selectors; if (selectors instanceof Array) { for (const selector of selectors) { callback(selector, div); } } else { callback(selectors, div); } } static divMode(divs, element) { if (!element || !divs) { return; } if (divs instanceof Array) { return divs.find((d) => checkSelector(element, d.selectors)); } else if (checkSelector(element, divs.selectors)) { return divs; } } static circleBounceDataFromParticle(p) { return { position: p.getPosition(), radius: p.getRadius(), mass: p.getMass(), velocity: p.velocity, factor: { horizontal: NumberUtils_1.NumberUtils.getValue(p.options.bounce.horizontal), vertical: NumberUtils_1.NumberUtils.getValue(p.options.bounce.vertical), }, }; } static circleBounce(p1, p2) { const xVelocityDiff = p1.velocity.x; const yVelocityDiff = p1.velocity.y; const pos1 = p1.position; const pos2 = p2.position; const xDist = pos2.x - pos1.x; const yDist = pos2.y - pos1.y; if (xVelocityDiff * xDist + yVelocityDiff * yDist >= 0) { const angle = -Math.atan2(pos2.y - pos1.y, pos2.x - pos1.x); const m1 = p1.mass; const m2 = p2.mass; const u1 = p1.velocity.rotate(angle); const u2 = p2.velocity.rotate(angle); const v1 = NumberUtils_1.NumberUtils.collisionVelocity(u1, u2, m1, m2); const v2 = NumberUtils_1.NumberUtils.collisionVelocity(u2, u1, m1, m2); const vFinal1 = v1.rotate(-angle); const vFinal2 = v2.rotate(-angle); p1.velocity.x = vFinal1.x * p1.factor.horizontal; p1.velocity.y = vFinal1.y * p1.factor.vertical; p2.velocity.x = vFinal2.x * p2.factor.horizontal; p2.velocity.y = vFinal2.y * p2.factor.vertical; } } static rectBounce(particle, divBounds) { const pPos = particle.getPosition(); const size = particle.getRadius(); const bounds = Utils.calculateBounds(pPos, size); const resH = rectSideBounce({ min: bounds.left, max: bounds.right, }, { min: bounds.top, max: bounds.bottom, }, { min: divBounds.left, max: divBounds.right, }, { min: divBounds.top, max: divBounds.bottom, }, particle.velocity.x, NumberUtils_1.NumberUtils.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({ min: bounds.top, max: bounds.bottom, }, { min: bounds.left, max: bounds.right, }, { min: divBounds.top, max: divBounds.bottom, }, { min: divBounds.left, max: divBounds.right, }, particle.velocity.y, NumberUtils_1.NumberUtils.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; } } } } exports.Utils = Utils;