UNPKG

party-js

Version:

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

167 lines (166 loc) 6.08 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ModuleBuilder = void 0; var components_1 = require("../components"); /** * Represents a builder for particle modules. Returns an evaluatable module * function, that can be consumed by emitters. * * @remarks * Not all properties can be driven. TypeScript will validate this at compile time, * but no internal validation is performed due to performance reasons. Also, note * that the driving factor is "lifetime" by default. * * @example * ```ts * new ModuleBuilder() * .drive("size") * .by((t) => t * 2) * .through("lifetime") * .build(); * ``` */ var ModuleBuilder = /** @class */ (function () { function ModuleBuilder() { /** * The factor driving the built function. * * @defaultValue "lifetime" */ this.factor = "lifetime"; this.isRelative = false; } /** * Specifies the key in the particle that should be driven. * * @remarks * Note that not all of a particle's properties are drivable through modules. If you * need full control of a particle inside of a module, you can use a module function directly. * * @returns The chained builder instance. */ ModuleBuilder.prototype.drive = function (key) { this.driverKey = key; return this; }; /** * Specifies the factor to drive the evaluated value by. Supports "lifetime" and "size". * * @returns The chained builder instance. */ ModuleBuilder.prototype.through = function (factor) { this.factor = factor; return this; }; /** * Specifies the value to drive the module behaviour by. This can be a constant, * a spline or an evaluable function. Note that in the last case, the driving * factor is passed as a parameter. * * @returns The chained builder instance. */ ModuleBuilder.prototype.by = function (driver) { this.driverValue = driver; return this; }; /** * Specifies that the module function is supposed to act relative to the * properties initial value. * * @remarks * Note that this is only possible if an "initial*" property exists on the * particle object. The operation applied to the initial and new value * is dependant on their type: * - `Vector`: Both vectors are added. * - `number`: Both numbers are multiplied. * * For more advanced relative customizations, consider using the particle * object in the driver value function instead, like: * ```ts * .by((t, p) => p.initialSize + t * 2); * ``` */ ModuleBuilder.prototype.relative = function (isRelative) { if (isRelative === void 0) { isRelative = true; } this.isRelative = isRelative; return this; }; /** * Consumes the builder and returns an evaluatable module function. * * @remarks * Note that you need to specify the driving key and value, otherwise an error * will be thrown. */ ModuleBuilder.prototype.build = function () { var _this = this; if (typeof this.driverKey === "undefined") { throw new Error("No driving key was provided in the module builder. Did you forget a '.drive()' call?"); } if (typeof this.driverValue === "undefined") { throw new Error("No driving value was provided in the module builder. Did you forget a '.through()' call?"); } return function (particle) { updateDrivenProperty(particle, _this.driverKey, evaluateModuleDriver(_this.driverValue, calculateModuleFactor(_this.factor, particle), particle), _this.isRelative); }; }; return ModuleBuilder; }()); exports.ModuleBuilder = ModuleBuilder; /** * Evaluates the module driver using a specified factor. */ function evaluateModuleDriver(driver, factor, particle) { if (typeof driver === "object" && "evaluate" in driver) { return driver.evaluate(factor); } if (typeof driver === "function") { return driver(factor, particle); } return driver; } /** * Calculates a module factor using a specified particle as context. */ function calculateModuleFactor(factor, particle) { switch (factor) { case "lifetime": return particle.initialLifetime - particle.lifetime; case "relativeLifetime": return ((particle.initialLifetime - particle.lifetime) / particle.initialLifetime); case "size": return particle.size; default: throw new Error("Invalid driving factor '" + factor + "'."); } } /** * Updates a driven property of a particle using the specified value. * * @remarks * If the operation is marked as relative, the function infers the new value * through the value's type. Note that relative properties must have a * corresponding "initial*" value in the particle's properties. */ function updateDrivenProperty(particle, key, value, relative) { if (relative === void 0) { relative = false; } if (!relative) { particle[key] = value; } else { var initial = particle["initial" + key[0].toUpperCase() + key.substr(1)]; if (typeof initial === "undefined") { throw new Error("Unable to use relative chaining with key '" + key + "'; no initial value exists."); } if (value instanceof components_1.Vector) { updateDrivenProperty(particle, key, initial.add(value)); } else if (typeof value === "number") { updateDrivenProperty(particle, key, initial * value); } else { throw new Error("Unable to use relative chaining with particle key '" + key + "'; no relative operation for '" + value + "' could be inferred."); } } }