UNPKG

party-js

Version:

A JavaScript library to brighten up your user's site experience with visual effects!

1,323 lines (1,240 loc) 92.7 kB
(function webpackUniversalModuleDefinition(root, factory) { if(typeof exports === 'object' && typeof module === 'object') module.exports = factory(); else if(typeof define === 'function' && define.amd) define("party", [], factory); else if(typeof exports === 'object') exports["party"] = factory(); else root["party"] = factory(); })(self, function() { return /******/ (() => { // webpackBootstrap /******/ "use strict"; /******/ var __webpack_modules__ = ({ /***/ "./src/components/circle.ts": /*!**********************************!*\ !*** ./src/components/circle.ts ***! \**********************************/ /***/ ((__unused_webpack_module, exports) => { Object.defineProperty(exports, "__esModule", ({ value: true })); exports.Circle = void 0; /** * Represents a circle. */ var Circle = /** @class */ (function () { /** * Creates a new circle at the specified coordinates, with a default radius of 0. */ function Circle(x, y, radius) { if (radius === void 0) { radius = 0; } this.x = x; this.y = y; this.radius = radius; } Circle.zero = new Circle(0, 0); return Circle; }()); exports.Circle = Circle; /***/ }), /***/ "./src/components/color.ts": /*!*********************************!*\ !*** ./src/components/color.ts ***! \*********************************/ /***/ ((__unused_webpack_module, exports, __webpack_require__) => { Object.defineProperty(exports, "__esModule", ({ value: true })); exports.Color = void 0; var math_1 = __webpack_require__(/*! ../systems/math */ "./src/systems/math.ts"); /** * Represents a color consisting of RGB values. The components of it are * represented as integers in the range 0 to 255. * * @example * ```ts * const a = new Color(12, 59, 219); * const b = Color.fromHex("#ffa68d"); * const result = a.mix(b); * ``` */ var Color = /** @class */ (function () { /** * Creates a new color instance from the specified RGB components. */ function Color(r, g, b) { this.values = new Float32Array(3); this.rgb = [r, g, b]; } Object.defineProperty(Color.prototype, "r", { /** * Returns the r-component of the color. */ get: function () { return this.values[0]; }, /** * Modifies the r-component of the color. * Note that this also floors the value. */ set: function (value) { this.values[0] = Math.floor(value); }, enumerable: false, configurable: true }); Object.defineProperty(Color.prototype, "g", { /** * Returns the g-component of the color. */ get: function () { return this.values[1]; }, /** * Modifies the g-component of the color. * Note that this also floors the value. */ set: function (value) { this.values[1] = Math.floor(value); }, enumerable: false, configurable: true }); Object.defineProperty(Color.prototype, "b", { /** * Returns the b-component of the color. * Note that this also floors the value. */ get: function () { return this.values[2]; }, /** * Modifies the b-component of the color. */ set: function (value) { this.values[2] = Math.floor(value); }, enumerable: false, configurable: true }); Object.defineProperty(Color.prototype, "rgb", { /** * Returns the rgb-components of the color, bundled as a copied array. */ get: function () { return [this.r, this.g, this.b]; }, /** * Simultaneously updates the rgb-components of the color, by passing an array. */ set: function (values) { this.r = values[0]; this.g = values[1]; this.b = values[2]; }, enumerable: false, configurable: true }); /** * Mixes the two color together with an optional mixing weight. * This weight is 0.5 by default, perfectly averaging the color. */ Color.prototype.mix = function (color, weight) { if (weight === void 0) { weight = 0.5; } return new Color(math_1.lerp(this.r, color.r, weight), math_1.lerp(this.g, color.g, weight), math_1.lerp(this.b, color.b, weight)); }; /** * Returns the hexadecimal representation of the color, prefixed by '#'. */ Color.prototype.toHex = function () { var hex = function (v) { return v.toString(16).padStart(2, "0"); }; return "#" + hex(this.r) + hex(this.g) + hex(this.b); }; /** * Returns a formatted representation of the color. */ Color.prototype.toString = function () { return "rgb(" + this.values.join(", ") + ")"; }; /** * Creates a color from the specified hexadecimal string. * This string can optionally be prefixed by '#'. */ Color.fromHex = function (hex) { if (hex.startsWith("#")) { hex = hex.substr(1); } return new Color(parseInt(hex.substr(0, 2), 16), parseInt(hex.substr(2, 2), 16), parseInt(hex.substr(4, 2), 16)); }; /** * Creates a color from the specified HSL components. * * @see https://stackoverflow.com/a/9493060/5507624 */ Color.fromHsl = function (h, s, l) { h /= 360; s /= 100; l /= 100; if (s === 0) { return new Color(l, l, l); } else { var hue2rgb = function (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; }; var to255 = function (v) { return Math.min(255, 256 * v); }; var q = l < 0.5 ? l * (1 + s) : l + s - l * s; var p = 2 * l - q; return new Color(to255(hue2rgb(p, q, h + 1 / 3)), to255(hue2rgb(p, q, h)), to255(hue2rgb(p, q, h - 1 / 3))); } }; /** * Returns (1, 1, 1). */ Color.white = new Color(255, 255, 255); /** * Returns (0, 0, 0). */ Color.black = new Color(0, 0, 0); return Color; }()); exports.Color = Color; /***/ }), /***/ "./src/components/gradient.ts": /*!************************************!*\ !*** ./src/components/gradient.ts ***! \************************************/ /***/ (function(__unused_webpack_module, exports, __webpack_require__) { var __extends = (this && this.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); var __spreadArray = (this && this.__spreadArray) || function (to, from) { for (var i = 0, il = from.length, j = to.length; i < il; i++, j++) to[j] = from[i]; return to; }; Object.defineProperty(exports, "__esModule", ({ value: true })); exports.Gradient = void 0; var spline_1 = __webpack_require__(/*! ./spline */ "./src/components/spline.ts"); /** * Represents a gradient that can be used to interpolate between multiple color. */ var Gradient = /** @class */ (function (_super) { __extends(Gradient, _super); function Gradient() { return _super !== null && _super.apply(this, arguments) || this; } /** * Interpolates between two color on the gradient. */ Gradient.prototype.interpolate = function (a, b, t) { return a.mix(b, t); }; /** * Returns a solid gradient from the given color. */ Gradient.solid = function (color) { return new Gradient({ value: color, time: 0.5 }); }; /** * Returns a gradient with evenly spaced keys from the given colors. */ Gradient.simple = function () { var colors = []; for (var _i = 0; _i < arguments.length; _i++) { colors[_i] = arguments[_i]; } var step = 1 / (colors.length - 1); return new (Gradient.bind.apply(Gradient, __spreadArray([void 0], colors.map(function (color, index) { return ({ value: color, time: index * step, }); }))))(); }; return Gradient; }(spline_1.Spline)); exports.Gradient = Gradient; /***/ }), /***/ "./src/components/index.ts": /*!*********************************!*\ !*** ./src/components/index.ts ***! \*********************************/ /***/ (function(__unused_webpack_module, exports, __webpack_require__) { var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __exportStar = (this && this.__exportStar) || function(m, exports) { for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); }; Object.defineProperty(exports, "__esModule", ({ value: true })); __exportStar(__webpack_require__(/*! ./circle */ "./src/components/circle.ts"), exports); __exportStar(__webpack_require__(/*! ./color */ "./src/components/color.ts"), exports); __exportStar(__webpack_require__(/*! ./gradient */ "./src/components/gradient.ts"), exports); __exportStar(__webpack_require__(/*! ./numericSpline */ "./src/components/numericSpline.ts"), exports); __exportStar(__webpack_require__(/*! ./rect */ "./src/components/rect.ts"), exports); __exportStar(__webpack_require__(/*! ./vector */ "./src/components/vector.ts"), exports); /***/ }), /***/ "./src/components/numericSpline.ts": /*!*****************************************!*\ !*** ./src/components/numericSpline.ts ***! \*****************************************/ /***/ (function(__unused_webpack_module, exports, __webpack_require__) { var __extends = (this && this.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); Object.defineProperty(exports, "__esModule", ({ value: true })); exports.NumericSpline = void 0; var math_1 = __webpack_require__(/*! ../systems/math */ "./src/systems/math.ts"); var spline_1 = __webpack_require__(/*! ./spline */ "./src/components/spline.ts"); /** * Represents a spline that can take numeric values. */ var NumericSpline = /** @class */ (function (_super) { __extends(NumericSpline, _super); function NumericSpline() { return _super !== null && _super.apply(this, arguments) || this; } /** * Smoothly interpolates between two keys on the spline. */ NumericSpline.prototype.interpolate = function (a, b, t) { return math_1.slerp(a, b, t); }; return NumericSpline; }(spline_1.Spline)); exports.NumericSpline = NumericSpline; /***/ }), /***/ "./src/components/rect.ts": /*!********************************!*\ !*** ./src/components/rect.ts ***! \********************************/ /***/ ((__unused_webpack_module, exports) => { Object.defineProperty(exports, "__esModule", ({ value: true })); exports.Rect = void 0; /** * Represents a rectangle with an origin and size. */ var Rect = /** @class */ (function () { function Rect(x, y, width, height) { if (width === void 0) { width = 0; } if (height === void 0) { height = 0; } this.x = x; this.y = y; this.width = width; this.height = height; } /** * Returns a new document-space rectangle from the viewport's bounds. */ Rect.fromScreen = function () { return new Rect(window.scrollX, window.scrollY, window.innerWidth, window.innerHeight); }; /** * Returns a new document-space rectangle from the specified element. */ Rect.fromElement = function (element) { var r = element.getBoundingClientRect(); return new Rect(window.scrollX + r.x, window.scrollY + r.y, r.width, r.height); }; Rect.zero = new Rect(0, 0); return Rect; }()); exports.Rect = Rect; /***/ }), /***/ "./src/components/spline.ts": /*!**********************************!*\ !*** ./src/components/spline.ts ***! \**********************************/ /***/ ((__unused_webpack_module, exports, __webpack_require__) => { Object.defineProperty(exports, "__esModule", ({ value: true })); exports.Spline = void 0; var math_1 = __webpack_require__(/*! ../systems/math */ "./src/systems/math.ts"); /** * Represents a spline that can be used to continueously evaluate a function * between keys. The base implementation is kept generic, so the functionality * can easily be implemented for similar constructs, such as gradients. */ var Spline = /** @class */ (function () { /** * Creates a new spline instance, using the specified keys. * Note that you have to pass at least one key. */ function Spline() { var keys = []; for (var _i = 0; _i < arguments.length; _i++) { keys[_i] = arguments[_i]; } if (keys.length === 0) { throw new Error("Splines require at least one key."); } if (Array.isArray(keys[0])) { throw new Error("You are trying to pass an array to the spline constructor, which is not supported. " + "Try to spread the array into the constructor instead."); } this.keys = keys; } /** * Evaluates the spline at the given time. */ Spline.prototype.evaluate = function (time) { if (this.keys.length === 0) { throw new Error("Attempt to evaluate a spline with no keys."); } if (this.keys.length === 1) { // The spline only contains one key, therefore is constant. return this.keys[0].value; } // Sort the keys and figure out the first key above the passed time. var ascendingKeys = this.keys.sort(function (a, b) { return a.time - b.time; }); var upperKeyIndex = ascendingKeys.findIndex(function (g) { return g.time > time; }); // If the found index is either 0 or -1, the specified time falls out // of the range of the supplied keys. In that case, the value of the // nearest applicant key is returned. if (upperKeyIndex === 0) { return ascendingKeys[0].value; } if (upperKeyIndex === -1) { return ascendingKeys[ascendingKeys.length - 1].value; } // Otherwise, find the bounding keys, and extrapolate the time between // the two. This is then used to interpolate between the two keys, // using the provided implementation. var lowerKey = ascendingKeys[upperKeyIndex - 1]; var upperKey = ascendingKeys[upperKeyIndex]; var containedTime = math_1.invlerp(lowerKey.time, upperKey.time, time); return this.interpolate(lowerKey.value, upperKey.value, containedTime); }; return Spline; }()); exports.Spline = Spline; /***/ }), /***/ "./src/components/vector.ts": /*!**********************************!*\ !*** ./src/components/vector.ts ***! \**********************************/ /***/ (function(__unused_webpack_module, exports, __webpack_require__) { var __spreadArray = (this && this.__spreadArray) || function (to, from) { for (var i = 0, il = from.length, j = to.length; i < il; i++, j++) to[j] = from[i]; return to; }; Object.defineProperty(exports, "__esModule", ({ value: true })); exports.Vector = void 0; var math_1 = __webpack_require__(/*! ../systems/math */ "./src/systems/math.ts"); /** * Represents a structure used to process vectors. * * @remarks * Note that the operations in this class will **not** modify the original vector, * except for the property assignments. This is to ensure that vectors are not * unintentionally modified. * * @example * ```ts * const vectorA = new Vector(1, 3, 5); * const vectorB = new Vector(2, 3, 1); * const vectorC = vectorA.add(vectorB); // (3, 6, 6) * ``` */ var Vector = /** @class */ (function () { /** * Creates a new vector with optional x-, y-, and z-components. * Omitted components are defaulted to 0. */ function Vector(x, y, z) { if (x === void 0) { x = 0; } if (y === void 0) { y = 0; } if (z === void 0) { z = 0; } this.values = new Float32Array(3); this.xyz = [x, y, z]; } Object.defineProperty(Vector.prototype, "x", { /** * Returns the x-component of the vector. */ get: function () { return this.values[0]; }, /** * Modifies the x-component of the vector. */ set: function (value) { this.values[0] = value; }, enumerable: false, configurable: true }); Object.defineProperty(Vector.prototype, "y", { /** * Returns the y-component of the vector. */ get: function () { return this.values[1]; }, /** * Modifies the y-component of the vector. */ set: function (value) { this.values[1] = value; }, enumerable: false, configurable: true }); Object.defineProperty(Vector.prototype, "z", { /** * Returns the z-component of the vector. */ get: function () { return this.values[2]; }, /** * Modifies the z-component of the vector. */ set: function (value) { this.values[2] = value; }, enumerable: false, configurable: true }); Object.defineProperty(Vector.prototype, "xyz", { /** * Returns the xyz-components of the vector, bundled as a copied array. */ get: function () { return [this.x, this.y, this.z]; }, /** * Simultaneously updates the xyz-components of the vector, by passing an array. */ set: function (values) { this.values[0] = values[0]; this.values[1] = values[1]; this.values[2] = values[2]; }, enumerable: false, configurable: true }); /** * Returns the length of the vector. */ Vector.prototype.magnitude = function () { return Math.sqrt(this.sqrMagnitude()); }; /** * Returns the squared length of the vector. */ Vector.prototype.sqrMagnitude = function () { return this.x * this.x + this.y * this.y + this.z * this.z; }; /** * Adds the two vectors together, component-wise. */ Vector.prototype.add = function (vector) { return new Vector(this.x + vector.x, this.y + vector.y, this.z + vector.z); }; /** * Subtracts the right vector from the left one, component-wise. */ Vector.prototype.subtract = function (vector) { return new Vector(this.x - vector.x, this.y - vector.y, this.z - vector.z); }; /** * Scales the lefthand vector by another vector or by a number. */ Vector.prototype.scale = function (scalar) { if (typeof scalar === "number") { return new Vector(this.x * scalar, this.y * scalar, this.z * scalar); } else { return new Vector(this.x * scalar.x, this.y * scalar.y, this.z * scalar.z); } }; /** * Normalizes the vector to a length of 1. If the length was previously zero, * then a zero-length vector will be returned. */ Vector.prototype.normalized = function () { var magnitude = this.magnitude(); if (magnitude !== 0) { return this.scale(1 / magnitude); } return new (Vector.bind.apply(Vector, __spreadArray([void 0], this.xyz)))(); }; /** * Returns the angle between two vectors, in degrees. */ Vector.prototype.angle = function (vector) { return (math_1.rad2deg * Math.acos((this.x * vector.x + this.y * vector.y + this.z * vector.z) / (this.magnitude() * vector.magnitude()))); }; /** * Returns the cross-product of two vectors. */ Vector.prototype.cross = function (vector) { return new Vector(this.y * vector.z - this.z * vector.y, this.z * vector.x - this.x * vector.z, this.x * vector.y - this.y * vector.x); }; /** * returns the dot-product of two vectors. */ Vector.prototype.dot = function (vector) { return (this.magnitude() * vector.magnitude() * Math.cos(math_1.deg2rad * this.angle(vector))); }; /** * Returns a formatted representation of the vector. */ Vector.prototype.toString = function () { return "Vector(" + this.values.join(", ") + ")"; }; /** * Creates a new vector from an angle, in degrees. Note that the z-component will be zero. */ Vector.from2dAngle = function (angle) { return new Vector(Math.cos(angle * math_1.deg2rad), Math.sin(angle * math_1.deg2rad)); }; /** * Returns (0, 0, 0). */ Vector.zero = new Vector(0, 0, 0); /** * Returns (1, 1, 1). */ Vector.one = new Vector(1, 1, 1); /** * Returns (1, 0, 0). */ Vector.right = new Vector(1, 0, 0); /** * Returns (0, 1, 0). */ Vector.up = new Vector(0, 1, 0); /** * Returns (0, 0, 1). */ Vector.forward = new Vector(0, 0, 1); return Vector; }()); exports.Vector = Vector; /***/ }), /***/ "./src/containers.ts": /*!***************************!*\ !*** ./src/containers.ts ***! \***************************/ /***/ ((__unused_webpack_module, exports, __webpack_require__) => { Object.defineProperty(exports, "__esModule", ({ value: true })); exports.particleContainer = exports.debugContainer = exports.rootContainer = void 0; var settings_1 = __webpack_require__(/*! ./settings */ "./src/settings.ts"); var util_1 = __webpack_require__(/*! ./util */ "./src/util/index.ts"); /** * The prefix to apply to the containers. */ var containerPrefix = "party-js-"; /** * Checks if the specified container is 'active', meaning not undefined and attached to the DOM. */ function isContainerActive(container) { return container && container.isConnected; } /** * A generic factory method for creating a DOM container. Prefixes the specified name with the * container prefix, applies the styles and adds it under the parent. */ function makeContainer(name, styles, parent) { var container = document.createElement("div"); container.id = containerPrefix + name; Object.assign(container.style, styles); return parent.appendChild(container); } /** * Represents the root container for DOM elements of the library. */ exports.rootContainer = new util_1.Lazy(function () { return makeContainer("container", { position: "fixed", left: "0", top: "0", height: "100vh", width: "100vw", pointerEvents: "none", userSelect: "none", zIndex: settings_1.settings.zIndex.toString(), }, document.body); }, isContainerActive); /** * Represents the debugging container of the library, only active if debugging is enabled. */ exports.debugContainer = new util_1.Lazy(function () { return makeContainer("debug", { position: "absolute", top: "0", left: "0", margin: "0.5em", padding: "0.5em 1em", border: "2px solid rgb(0, 0, 0, 0.2)", background: "rgb(0, 0, 0, 0.1)", color: "#555", fontFamily: "monospace", }, exports.rootContainer.current); }, isContainerActive); /** * Represents the particle container of the library. * This is where the particle DOM elements get rendered into. */ exports.particleContainer = new util_1.Lazy(function () { return makeContainer("particles", { width: "100%", height: "100%", overflow: "hidden", perspective: "1200px", }, exports.rootContainer.current); }, isContainerActive); /***/ }), /***/ "./src/debug.ts": /*!**********************!*\ !*** ./src/debug.ts ***! \**********************/ /***/ (function(__unused_webpack_module, exports, __webpack_require__) { var __spreadArray = (this && this.__spreadArray) || function (to, from) { for (var i = 0, il = from.length, j = to.length; i < il; i++, j++) to[j] = from[i]; return to; }; Object.defineProperty(exports, "__esModule", ({ value: true })); exports.Debug = void 0; var containers_1 = __webpack_require__(/*! ./containers */ "./src/containers.ts"); var settings_1 = __webpack_require__(/*! ./settings */ "./src/settings.ts"); /** * Represents a utility module to view debug information inside the DOM. * This is disabled by default and needs to manually be enabled by setting * the '.enabled' field to true. * * While disabled, the utility will not fetch stats and update itself. */ var Debug = /** @class */ (function () { /** * Registers a new debug utility that is attached to the given scene. * * @param scene The scene to attach to. */ function Debug(scene) { this.scene = scene; /** * The rate at which the debug interface should refresh itself (per second). */ this.refreshRate = 8; /** * The timer counting down to refreshes. */ this.refreshTimer = 1 / this.refreshRate; } /** * Processes a tick event in the interface. This checks if enough has passed to * trigger a refresh, and if so, fetches the debug information and updates the DOM. * * @param delta The time that has elapsed since the last tick. */ Debug.prototype.tick = function (delta) { var container = containers_1.debugContainer.current; // If the current display style does not match the style inferred from the // enabled-state, update it. var displayStyle = settings_1.settings.debug ? "block" : "none"; if (container.style.display !== displayStyle) { container.style.display = displayStyle; } if (!settings_1.settings.debug) { // If the interface is not enabled, don't fetch or update any infos. return; } this.refreshTimer += delta; if (this.refreshTimer > 1 / this.refreshRate) { this.refreshTimer = 0; // Update the container with the fetched information joined on line breaks. container.innerHTML = this.getDebugInformation(delta).join("<br>"); } }; /** * Fetches the debug information from the specified delta and the linked scene. * * @returns An array of debugging information, formatted as HTML. */ Debug.prototype.getDebugInformation = function (delta) { // Count emitters and particles. var emitters = this.scene.emitters.length; var particles = this.scene.emitters.reduce(function (acc, cur) { return acc + cur.particles.length; }, 0); var infos = [ "<b>party.js Debug</b>", "--------------", "FPS: " + Math.round(1 / delta), "Emitters: " + emitters, "Particles: " + particles, ]; // Emitter informations are formatted using their index, internal timer // and total particle count. var emitterInfos = this.scene.emitters.map(function (emitter) { return [ // Show the current loop and the total loops. "\u2B6F: " + (emitter["currentLoop"] + 1) + "/" + (emitter.options.loops >= 0 ? emitter.options.loops : "∞"), // Show the amount of particle contained. "\u03A3p: " + emitter.particles.length, // Show the internal timer. !emitter.isExpired ? "\u03A3t: " + emitter["durationTimer"].toFixed(3) + "s" : "<i>expired</i>", ].join(", "); }); infos.push.apply(infos, __spreadArray(["--------------"], emitterInfos)); return infos; }; return Debug; }()); exports.Debug = Debug; /***/ }), /***/ "./src/index.ts": /*!**********************!*\ !*** ./src/index.ts ***! \**********************/ /***/ (function(__unused_webpack_module, exports, __webpack_require__) { var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __exportStar = (this && this.__exportStar) || function(m, exports) { for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); }; Object.defineProperty(exports, "__esModule", ({ value: true })); exports.default = exports.forceInit = exports.util = exports.math = exports.random = exports.sources = exports.variation = exports.Emitter = exports.Particle = exports.settings = exports.scene = void 0; var scene_1 = __webpack_require__(/*! ./scene */ "./src/scene.ts"); var util_1 = __webpack_require__(/*! ./util */ "./src/util/index.ts"); __exportStar(__webpack_require__(/*! ./components */ "./src/components/index.ts"), exports); __exportStar(__webpack_require__(/*! ./templates */ "./src/templates/index.ts"), exports); __exportStar(__webpack_require__(/*! ./systems/shapes */ "./src/systems/shapes.ts"), exports); __exportStar(__webpack_require__(/*! ./systems/modules */ "./src/systems/modules.ts"), exports); // Create the lazy-initializing scene. exports.scene = new util_1.Lazy(function () { // The library requires the use of the DOM, hence it cannot run in non-browser environments. if (typeof document === "undefined" || typeof window === "undefined") { throw new Error("It seems like you are trying to run party.js in a non-browser-like environment, which is not supported."); } return new scene_1.Scene(); }); var settings_1 = __webpack_require__(/*! ./settings */ "./src/settings.ts"); Object.defineProperty(exports, "settings", ({ enumerable: true, get: function () { return settings_1.settings; } })); var particle_1 = __webpack_require__(/*! ./particles/particle */ "./src/particles/particle.ts"); Object.defineProperty(exports, "Particle", ({ enumerable: true, get: function () { return particle_1.Particle; } })); var emitter_1 = __webpack_require__(/*! ./particles/emitter */ "./src/particles/emitter.ts"); Object.defineProperty(exports, "Emitter", ({ enumerable: true, get: function () { return emitter_1.Emitter; } })); exports.variation = __webpack_require__(/*! ./systems/variation */ "./src/systems/variation.ts"); exports.sources = __webpack_require__(/*! ./systems/sources */ "./src/systems/sources.ts"); exports.random = __webpack_require__(/*! ./systems/random */ "./src/systems/random.ts"); exports.math = __webpack_require__(/*! ./systems/math */ "./src/systems/math.ts"); exports.util = __webpack_require__(/*! ./util */ "./src/util/index.ts"); /** * Forces the initialization of the otherwise lazy scene. */ function forceInit() { exports.scene.current; } exports.forceInit = forceInit; exports.default = __webpack_require__(/*! ./ */ "./src/index.ts"); /***/ }), /***/ "./src/particles/emitter.ts": /*!**********************************!*\ !*** ./src/particles/emitter.ts ***! \**********************************/ /***/ ((__unused_webpack_module, exports, __webpack_require__) => { Object.defineProperty(exports, "__esModule", ({ value: true })); exports.Emitter = void 0; var vector_1 = __webpack_require__(/*! ../components/vector */ "./src/components/vector.ts"); var settings_1 = __webpack_require__(/*! ../settings */ "./src/settings.ts"); var variation_1 = __webpack_require__(/*! ../systems/variation */ "./src/systems/variation.ts"); var config_1 = __webpack_require__(/*! ../util/config */ "./src/util/config.ts"); var options_1 = __webpack_require__(/*! ./options */ "./src/particles/options/index.ts"); var particle_1 = __webpack_require__(/*! ./particle */ "./src/particles/particle.ts"); /** * Represents an emitter that is responsible for spawning and updating particles. * * Particles themselves are just data-holders, with the system acting upon them and * modifying them. The modifications are done mainly via modules, that use the * particle's data together with some function to apply temporal transitions. * * @see Particle * @see ParticleModifierModule */ var Emitter = /** @class */ (function () { /** * Creates a new emitter, using default options. */ function Emitter(options) { /** * The particles currently contained within the system. */ this.particles = []; this.currentLoop = 0; // The current loop index. this.durationTimer = 0; // Measures the current runtime duration, to allow loops to reset. this.emissionTimer = 0; // Measures the current emission timer, to allow spawning particles in intervals. this.attemptedBurstIndices = []; // The indices of the particle bursts that were attempted this loop. this.options = config_1.overrideDefaults(options_1.getDefaultEmitterOptions(), options === null || options === void 0 ? void 0 : options.emitterOptions); this.emission = config_1.overrideDefaults(options_1.getDefaultEmissionOptions(), options === null || options === void 0 ? void 0 : options.emissionOptions); this.renderer = config_1.overrideDefaults(options_1.getDefaultRendererOptions(), options === null || options === void 0 ? void 0 : options.rendererOptions); } Object.defineProperty(Emitter.prototype, "isExpired", { /** * Checks if the emitter is already expired and can be removed. * Expired emitters do not emit new particles. */ get: function () { return (this.options.loops >= 0 && this.currentLoop >= this.options.loops); }, enumerable: false, configurable: true }); Object.defineProperty(Emitter.prototype, "canRemove", { /** * Checks if the emitter can safely be removed. * This is true if no more particles are active. */ get: function () { return this.particles.length === 0; }, enumerable: false, configurable: true }); /** * Clears all particles inside the emitter. * * @returns The number of cleared particles. */ Emitter.prototype.clearParticles = function () { return this.particles.splice(0).length; }; /** * Processes a tick of the emitter, using the elapsed time. * * @remarks * This handles a few things, namely: * - Incrementing the duration timer and potentially incrementing the loop. * - Handling particle bursts & emissions. * - Despawning particles conditionally. * * @param delta The time, in seconds, passed since the last tick. */ Emitter.prototype.tick = function (delta) { if (!this.isExpired) { this.durationTimer += delta; if (this.durationTimer >= this.options.duration) { this.currentLoop++; // To start a new loop, the duration timer and attempted bursts are reset. this.durationTimer = 0; this.attemptedBurstIndices = []; } // We need to check the expiry again, in case the added loop or duration changed something. if (!this.isExpired) { // Iterate over the bursts, attempting to execute them if the time is ready. var burstIndex = 0; for (var _i = 0, _a = this.emission.bursts; _i < _a.length; _i++) { var burst = _a[_i]; if (burst.time <= this.durationTimer) { // Has the burst already been attempted? If not ... if (!this.attemptedBurstIndices.includes(burstIndex)) { // Perform the burst, emitting a variable amount of particles. var count = variation_1.evaluateVariation(burst.count); for (var i = 0; i < count; i++) { this.emitParticle(); } // Mark the burst as attempted. this.attemptedBurstIndices.push(burstIndex); } } burstIndex++; } // Handle the 'emission over time'. By using a while-loop instead of a simple // if-condition, we take high deltas into account, and ensure that the correct // number of particles will consistently be emitted. this.emissionTimer += delta; var delay = 1 / this.emission.rate; while (this.emissionTimer > delay) { this.emissionTimer -= delay; this.emitParticle(); } } } var _loop_1 = function (i) { var particle = this_1.particles[i]; this_1.tickParticle(particle, delta); // Particles should be despawned (i.e. removed from the collection) if any of // the despawning rules apply to them. if (this_1.options.despawningRules.some(function (rule) { return rule(particle); })) { this_1.particles.splice(i, 1); } }; var this_1 = this; for (var i = this.particles.length - 1; i >= 0; i--) { _loop_1(i); } }; /** * Performs an internal tick for the particle. * * @remarks * This method controls the particle's lifetime, location and velocity, according * to the elapsed delta and the configuration. Additionally, each of the emitter's * modules is applied to the particle. * * @param particle The particle to apply the tick for. * @param delta The time, in seconds, passed since the last tick. */ Emitter.prototype.tickParticle = function (particle, delta) { particle.lifetime -= delta; if (this.options.useGravity) { // Apply gravitational acceleration to the particle. particle.velocity = particle.velocity.add(vector_1.Vector.up.scale(settings_1.settings.gravity * delta)); } // Apply the particle's velocity to its location. particle.location = particle.location.add(particle.velocity.scale(delta)); // Apply the modules to the particle. for (var _i = 0, _a = this.options.modules; _i < _a.length; _i++) { var moduleFunction = _a[_i]; moduleFunction(particle); } }; /** * Emits a particle using the registered settings. * Also may despawn a particle if the maximum number of particles is exceeded. */ Emitter.prototype.emitParticle = function () { var particle = new particle_1.Particle({ location: this.emission.sourceSampler(), lifetime: variation_1.evaluateVariation(this.emission.initialLifetime), velocity: vector_1.Vector.from2dAngle(variation_1.evaluateVariation(this.emission.angle)).scale(variation_1.evaluateVariation(this.emission.initialSpeed)), size: variation_1.evaluateVariation(this.emission.initialSize), rotation: variation_1.evaluateVariation(this.emission.initialRotation), color: variation_1.evaluateVariation(this.emission.initialColor), }); this.particles.push(particle); // Ensure that no more particles than 'maxParticles' can exist. if (this.particles.length > this.options.maxParticles) { this.particles.shift(); } return particle; }; return Emitter; }()); exports.Emitter = Emitter; /***/ }), /***/ "./src/particles/options/emissionOptions.ts": /*!**************************************************!*\ !*** ./src/particles/options/emissionOptions.ts ***! \**************************************************/ /***/ ((__unused_webpack_module, exports, __webpack_require__) => { Object.defineProperty(exports, "__esModule", ({ value: true })); exports.getDefaultEmissionOptions = void 0; var components_1 = __webpack_require__(/*! ../../components */ "./src/components/index.ts"); var sources_1 = __webpack_require__(/*! ../../systems/sources */ "./src/systems/sources.ts"); /** * Returns the default set of emission options. */ function getDefaultEmissionOptions() { return { rate: 10, angle: 0, bursts: [], sourceSampler: sources_1.rectSource(components_1.Rect.zero), initialLifetime: 5, initialSpeed: 5, initialSize: 1, initialRotation: components_1.Vector.zero, initialColor: components_1.Color.white, }; } exports.getDefaultEmissionOptions = getDefaultEmissionOptions; /***/ }), /***/ "./src/particles/options/emitterOptions.ts": /*!*************************************************!*\ !*** ./src/particles/options/emitterOptions.ts ***! \*************************************************/ /***/ ((__unused_webpack_module, exports, __webpack_require__) => { Object.defineProperty(exports, "__esModule", ({ value: true })); exports.getDefaultEmitterOptions = void 0; var rules_1 = __webpack_require__(/*! ../../util/rules */ "./src/util/rules.ts"); /** * Returns the default set of emitter options. */ function getDefaultEmitterOptions() { return { duration: 5, loops: 1, useGravity: true, maxParticles: 300, despawningRules: [rules_1.despawningRules.lifetime, rules_1.despawningRules.bounds], modules: [], }; } exports.getDefaultEmitterOptions = getDefaultEmitterOptions; /***/ }), /***/ "./src/particles/options/index.ts": /*!****************************************!*\ !*** ./src/particles/options/index.ts ***! \****************************************/ /***/ (function(__unused_webpack_module, exports, __webpack_require__) { var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __exportStar = (this && this.__exportStar) || function(m, exports) { for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); }; Object.defineProperty(exports, "__esModule", ({ value: true })); __exportStar(__webpack_require__(/*! ./emitterOptions */ "./src/particles/options/emitterOptions.ts"), exports); __exportStar(__webpack_require__(/*! ./emissionOptions */ "./src/particles/options/emissionOptions.ts"), exports); __exportStar(__webpack_require__(/*! ./renderOptions */ "./src/particles/options/renderOptions.ts"), exports); /***/ }), /***/ "./src/particles/options/renderOptions.ts": /*!************************************************!*\ !*** ./src/particles/options/renderOptions.ts ***! \************************************************/ /***/ ((__unused_webpack_module, exports) => { Object.defineProperty(exports, "__esModule", ({ value: true })); exports.getDefaultRendererOptions = void 0; /** * Returns the default set of renderer options. */ function getDefaultRendererOptions() { return { shapeFactory: "square", applyColor: defaultApplyColor, applyOpacity: defaultApplyOpacity, applyLighting: defaultApplyLighting, applyTransform: defaultApplyTransform, }; } exports.getDefaultRendererOptions = getDefaultRendererOptions; /** * Applies the specified color to the element. * * @remarks * This function is aware of the element's node type: * - `div` elements have their `background` set. * - `svg` elements have their `fill` and `color` set. * - Other elements have their `color` set. */ function defaultApplyColor(color, element) { var hex = color.toHex(); // Note that by default, HTML node names are uppercase. switch (element.nodeName.toLowerCase()) { case "div": element.style.background = hex; break; case "svg": element.style.fill = element.style.color = hex; break; default: element.style.color = hex; break; } } /** * Applies the specified opacity to the element. */ function defaultApplyOpacity(opacity, element) { element.style.opacity = opacity.toString(); } /** * Applies the specified lighting to the element as a brightness filter. * * @remarks * This function assumes an ambient light with intensity 0.5, and that the * particle should be lit from both sides. The brightness filter can exceed 1, * to give the particles a "glossy" feel. */ function defaultApplyLighting(lighting, element) { element.style.filter = "brightness(" + (0.5 + Math.abs(lighting)) + ")"; } /** * Applies the specified transform to the element as a 3D CSS transform. * Also takes into account the current window scroll, to make sure that particles are * rendered inside of the fixed container. */ function defaultApplyTransform(particle, element) { element.style.transform = // Make sure to take window scrolling into account. "translateX(" + (particle.location.x - window.scrollX).toFixed(3) + "px) " + ("translateY(" + (particle.location.y - window.scrollY).toFixed(3) + "px) ") + ("translateZ(" + particle.location.z.toFixed(3) + "px) ") + ("rotateX(" + particle.rotation.x.toFixed(3) + "deg) ") + ("rotateY(" + particle.rotation.y.toFixed(3) + "deg) ") + ("rotateZ(" + particle.rotation.z.toFixed(3) + "deg) ") + ("scale(" + particle.size.toFixed(3) + ")"); } /***/ }), /***/ "./src/particles/particle.ts": /*!***********************************!*\ !*** ./src/particles/particle.ts ***! \***********************************/ /***/ ((__unused_webpack_module, exports, __webpack_require__) => { Object.defineProperty(exports, "__esModule", ({ value: true })); exports.Particle = void 0; var components_1 = __webpack_require__(/*! ../components */ "./src/components/index.ts"); var config_1 = __webpack_require__(/*! ../util/config */ "./src/util/config.ts"); /** * Represents an emitted particle. */ var Particle = /** @class */ (function () { /** * Creates a new particle instance through the specified options. */ function Particle(options) { var populatedOptions = config_1.overrideDefaults({ lifetime: 0, size: 1, location: components_1.Vector.zero, rotation: components_1.Vector.zero, velocity: components_1.Vector.zero, color: components_1.Color.white, opacity: 1, }, options); // Generate a symbolic ID. this.id = Symbol(); // Assign various properties, together with some initials for later reference. this.size = this.initial