pixi.js
Version:
<p align="center"> <a href="https://pixijs.com" target="_blank" rel="noopener noreferrer"> <img height="150" src="https://files.pixijs.download/branding/pixijs-logo-transparent-dark.svg?v=1" alt="PixiJS logo"> </a> </p> <br/> <p align="center">
1,289 lines (1,228 loc) • 1.78 MB
JavaScript
/*!
* PixiJS - v8.10.1
* Compiled Thu, 05 Jun 2025 17:35:59 UTC
*
* PixiJS is licensed under the MIT License.
* http://www.opensource.org/licenses/mit-license
*/
"use strict";
var __defProp$1d = Object.defineProperty;
var __defProps$r = Object.defineProperties;
var __getOwnPropDescs$r = Object.getOwnPropertyDescriptors;
var __getOwnPropSymbols$1d = Object.getOwnPropertySymbols;
var __hasOwnProp$1d = Object.prototype.hasOwnProperty;
var __propIsEnum$1d = Object.prototype.propertyIsEnumerable;
var __defNormalProp$1d = (obj, key, value) => key in obj ? __defProp$1d(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __spreadValues$1d = (a, b) => {
for (var prop in b || (b = {}))
if (__hasOwnProp$1d.call(b, prop))
__defNormalProp$1d(a, prop, b[prop]);
if (__getOwnPropSymbols$1d)
for (var prop of __getOwnPropSymbols$1d(b)) {
if (__propIsEnum$1d.call(b, prop))
__defNormalProp$1d(a, prop, b[prop]);
}
return a;
};
var __spreadProps$r = (a, b) => __defProps$r(a, __getOwnPropDescs$r(b));
var ExtensionType = /* @__PURE__ */ ((ExtensionType2) => {
ExtensionType2["Application"] = "application";
ExtensionType2["WebGLPipes"] = "webgl-pipes";
ExtensionType2["WebGLPipesAdaptor"] = "webgl-pipes-adaptor";
ExtensionType2["WebGLSystem"] = "webgl-system";
ExtensionType2["WebGPUPipes"] = "webgpu-pipes";
ExtensionType2["WebGPUPipesAdaptor"] = "webgpu-pipes-adaptor";
ExtensionType2["WebGPUSystem"] = "webgpu-system";
ExtensionType2["CanvasSystem"] = "canvas-system";
ExtensionType2["CanvasPipesAdaptor"] = "canvas-pipes-adaptor";
ExtensionType2["CanvasPipes"] = "canvas-pipes";
ExtensionType2["Asset"] = "asset";
ExtensionType2["LoadParser"] = "load-parser";
ExtensionType2["ResolveParser"] = "resolve-parser";
ExtensionType2["CacheParser"] = "cache-parser";
ExtensionType2["DetectionParser"] = "detection-parser";
ExtensionType2["MaskEffect"] = "mask-effect";
ExtensionType2["BlendMode"] = "blend-mode";
ExtensionType2["TextureSource"] = "texture-source";
ExtensionType2["Environment"] = "environment";
ExtensionType2["ShapeBuilder"] = "shape-builder";
ExtensionType2["Batcher"] = "batcher";
return ExtensionType2;
})(ExtensionType || {});
const normalizeExtension = (ext) => {
if (typeof ext === "function" || typeof ext === "object" && ext.extension) {
if (!ext.extension) {
throw new Error("Extension class must have an extension object");
}
const metadata = typeof ext.extension !== "object" ? { type: ext.extension } : ext.extension;
ext = __spreadProps$r(__spreadValues$1d({}, metadata), { ref: ext });
}
if (typeof ext === "object") {
ext = __spreadValues$1d({}, ext);
} else {
throw new Error("Invalid extension type");
}
if (typeof ext.type === "string") {
ext.type = [ext.type];
}
return ext;
};
const normalizeExtensionPriority = (ext, defaultPriority) => {
var _a;
return (_a = normalizeExtension(ext).priority) != null ? _a : defaultPriority;
};
const extensions = {
/** @ignore */
_addHandlers: {},
/** @ignore */
_removeHandlers: {},
/** @ignore */
_queue: {},
/**
* Remove extensions from PixiJS.
* @param extensions - Extensions to be removed. Can be:
* - Extension class with static `extension` property
* - Extension format object with `type` and `ref`
* - Multiple extensions as separate arguments
* @returns {extensions} this for chaining
* @example
* ```ts
* // Remove a single extension
* extensions.remove(MyRendererPlugin);
*
* // Remove multiple extensions
* extensions.remove(
* MyRendererPlugin,
* MySystemPlugin
* );
* ```
* @see {@link ExtensionType} For available extension types
* @see {@link ExtensionFormat} For extension format details
*/
remove(...extensions2) {
extensions2.map(normalizeExtension).forEach((ext) => {
ext.type.forEach((type) => {
var _a, _b;
return (_b = (_a = this._removeHandlers)[type]) == null ? void 0 : _b.call(_a, ext);
});
});
return this;
},
/**
* Register new extensions with PixiJS. Extensions can be registered in multiple formats:
* - As a class with a static `extension` property
* - As an extension format object
* - As multiple extensions passed as separate arguments
* @param extensions - Extensions to add to PixiJS. Each can be:
* - A class with static `extension` property
* - An extension format object with `type` and `ref`
* - Multiple extensions as separate arguments
* @returns This extensions instance for chaining
* @example
* ```ts
* // Register a simple extension
* extensions.add(MyRendererPlugin);
*
* // Register multiple extensions
* extensions.add(
* MyRendererPlugin,
* MySystemPlugin,
* });
* ```
* @see {@link ExtensionType} For available extension types
* @see {@link ExtensionFormat} For extension format details
* @see {@link extensions.remove} For removing registered extensions
*/
add(...extensions2) {
extensions2.map(normalizeExtension).forEach((ext) => {
ext.type.forEach((type) => {
var _a, _b;
const handlers = this._addHandlers;
const queue = this._queue;
if (!handlers[type]) {
queue[type] = queue[type] || [];
(_a = queue[type]) == null ? void 0 : _a.push(ext);
} else {
(_b = handlers[type]) == null ? void 0 : _b.call(handlers, ext);
}
});
});
return this;
},
/**
* Internal method to handle extensions by name.
* @param type - The extension type.
* @param onAdd - Function handler when extensions are added/registered {@link StrictExtensionFormat}.
* @param onRemove - Function handler when extensions are removed/unregistered {@link StrictExtensionFormat}.
* @returns this for chaining.
* @internal
* @ignore
*/
handle(type, onAdd, onRemove) {
var _a;
const addHandlers = this._addHandlers;
const removeHandlers = this._removeHandlers;
if (addHandlers[type] || removeHandlers[type]) {
throw new Error(`Extension type ${type} already has a handler`);
}
addHandlers[type] = onAdd;
removeHandlers[type] = onRemove;
const queue = this._queue;
if (queue[type]) {
(_a = queue[type]) == null ? void 0 : _a.forEach((ext) => onAdd(ext));
delete queue[type];
}
return this;
},
/**
* Handle a type, but using a map by `name` property.
* @param type - Type of extension to handle.
* @param map - The object map of named extensions.
* @returns this for chaining.
* @ignore
*/
handleByMap(type, map) {
return this.handle(
type,
(extension) => {
if (extension.name) {
map[extension.name] = extension.ref;
}
},
(extension) => {
if (extension.name) {
delete map[extension.name];
}
}
);
},
/**
* Handle a type, but using a list of extensions with a `name` property.
* @param type - Type of extension to handle.
* @param map - The array of named extensions.
* @param defaultPriority - Fallback priority if none is defined.
* @returns this for chaining.
* @ignore
*/
handleByNamedList(type, map, defaultPriority = -1) {
return this.handle(
type,
(extension) => {
const index = map.findIndex((item) => item.name === extension.name);
if (index >= 0)
return;
map.push({ name: extension.name, value: extension.ref });
map.sort((a, b) => normalizeExtensionPriority(b.value, defaultPriority) - normalizeExtensionPriority(a.value, defaultPriority));
},
(extension) => {
const index = map.findIndex((item) => item.name === extension.name);
if (index !== -1) {
map.splice(index, 1);
}
}
);
},
/**
* Handle a type, but using a list of extensions.
* @param type - Type of extension to handle.
* @param list - The list of extensions.
* @param defaultPriority - The default priority to use if none is specified.
* @returns this for chaining.
* @ignore
*/
handleByList(type, list, defaultPriority = -1) {
return this.handle(
type,
(extension) => {
if (list.includes(extension.ref)) {
return;
}
list.push(extension.ref);
list.sort((a, b) => normalizeExtensionPriority(b, defaultPriority) - normalizeExtensionPriority(a, defaultPriority));
},
(extension) => {
const index = list.indexOf(extension.ref);
if (index !== -1) {
list.splice(index, 1);
}
}
);
},
/**
* Mixin the source object(s) properties into the target class's prototype.
* Copies all property descriptors from source objects to the target's prototype.
* @param Target - The target class to mix properties into
* @param sources - One or more source objects containing properties to mix in
* @example
* ```ts
* // Create a mixin with shared properties
* const moveable = {
* x: 0,
* y: 0,
* move(x: number, y: number) {
* this.x += x;
* this.y += y;
* }
* };
*
* // Create a mixin with computed properties
* const scalable = {
* scale: 1,
* get scaled() {
* return this.scale > 1;
* }
* };
*
* // Apply mixins to a class
* extensions.mixin(Sprite, moveable, scalable);
*
* // Use mixed-in properties
* const sprite = new Sprite();
* sprite.move(10, 20);
* console.log(sprite.x, sprite.y); // 10, 20
* ```
* @remarks
* - Copies all properties including getters/setters
* - Does not modify source objects
* - Preserves property descriptors
* @see {@link Object.defineProperties} For details on property descriptors
* @see {@link Object.getOwnPropertyDescriptors} For details on property copying
*/
mixin(Target, ...sources) {
for (const source of sources) {
Object.defineProperties(Target.prototype, Object.getOwnPropertyDescriptors(source));
}
}
};
var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
function getDefaultExportFromCjs (x) {
return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
}
function getDefaultExportFromNamespaceIfPresent (n) {
return n && Object.prototype.hasOwnProperty.call(n, 'default') ? n['default'] : n;
}
function getDefaultExportFromNamespaceIfNotNamed (n) {
return n && Object.prototype.hasOwnProperty.call(n, 'default') && Object.keys(n).length === 1 ? n['default'] : n;
}
function getAugmentedNamespace(n) {
if (n.__esModule) return n;
var f = n.default;
if (typeof f == "function") {
var a = function a () {
if (this instanceof a) {
return Reflect.construct(f, arguments, this.constructor);
}
return f.apply(this, arguments);
};
a.prototype = f.prototype;
} else a = {};
Object.defineProperty(a, '__esModule', {value: true});
Object.keys(n).forEach(function (k) {
var d = Object.getOwnPropertyDescriptor(n, k);
Object.defineProperty(a, k, d.get ? d : {
enumerable: true,
get: function () {
return n[k];
}
});
});
return a;
}
var eventemitter3$1 = {exports: {}};
var eventemitter3 = eventemitter3$1.exports;
(function (module) {
'use strict';
var has = Object.prototype.hasOwnProperty
, prefix = '~';
/**
* Constructor to create a storage for our `EE` objects.
* An `Events` instance is a plain object whose properties are event names.
*
* @constructor
* @private
*/
function Events() {}
//
// We try to not inherit from `Object.prototype`. In some engines creating an
// instance in this way is faster than calling `Object.create(null)` directly.
// If `Object.create(null)` is not supported we prefix the event names with a
// character to make sure that the built-in object properties are not
// overridden or used as an attack vector.
//
if (Object.create) {
Events.prototype = Object.create(null);
//
// This hack is needed because the `__proto__` property is still inherited in
// some old browsers like Android 4, iPhone 5.1, Opera 11 and Safari 5.
//
if (!new Events().__proto__) prefix = false;
}
/**
* Representation of a single event listener.
*
* @param {Function} fn The listener function.
* @param {*} context The context to invoke the listener with.
* @param {Boolean} [once=false] Specify if the listener is a one-time listener.
* @constructor
* @private
*/
function EE(fn, context, once) {
this.fn = fn;
this.context = context;
this.once = once || false;
}
/**
* Add a listener for a given event.
*
* @param {EventEmitter} emitter Reference to the `EventEmitter` instance.
* @param {(String|Symbol)} event The event name.
* @param {Function} fn The listener function.
* @param {*} context The context to invoke the listener with.
* @param {Boolean} once Specify if the listener is a one-time listener.
* @returns {EventEmitter}
* @private
*/
function addListener(emitter, event, fn, context, once) {
if (typeof fn !== 'function') {
throw new TypeError('The listener must be a function');
}
var listener = new EE(fn, context || emitter, once)
, evt = prefix ? prefix + event : event;
if (!emitter._events[evt]) emitter._events[evt] = listener, emitter._eventsCount++;
else if (!emitter._events[evt].fn) emitter._events[evt].push(listener);
else emitter._events[evt] = [emitter._events[evt], listener];
return emitter;
}
/**
* Clear event by name.
*
* @param {EventEmitter} emitter Reference to the `EventEmitter` instance.
* @param {(String|Symbol)} evt The Event name.
* @private
*/
function clearEvent(emitter, evt) {
if (--emitter._eventsCount === 0) emitter._events = new Events();
else delete emitter._events[evt];
}
/**
* Minimal `EventEmitter` interface that is molded against the Node.js
* `EventEmitter` interface.
*
* @constructor
* @public
*/
function EventEmitter() {
this._events = new Events();
this._eventsCount = 0;
}
/**
* Return an array listing the events for which the emitter has registered
* listeners.
*
* @returns {Array}
* @public
*/
EventEmitter.prototype.eventNames = function eventNames() {
var names = []
, events
, name;
if (this._eventsCount === 0) return names;
for (name in (events = this._events)) {
if (has.call(events, name)) names.push(prefix ? name.slice(1) : name);
}
if (Object.getOwnPropertySymbols) {
return names.concat(Object.getOwnPropertySymbols(events));
}
return names;
};
/**
* Return the listeners registered for a given event.
*
* @param {(String|Symbol)} event The event name.
* @returns {Array} The registered listeners.
* @public
*/
EventEmitter.prototype.listeners = function listeners(event) {
var evt = prefix ? prefix + event : event
, handlers = this._events[evt];
if (!handlers) return [];
if (handlers.fn) return [handlers.fn];
for (var i = 0, l = handlers.length, ee = new Array(l); i < l; i++) {
ee[i] = handlers[i].fn;
}
return ee;
};
/**
* Return the number of listeners listening to a given event.
*
* @param {(String|Symbol)} event The event name.
* @returns {Number} The number of listeners.
* @public
*/
EventEmitter.prototype.listenerCount = function listenerCount(event) {
var evt = prefix ? prefix + event : event
, listeners = this._events[evt];
if (!listeners) return 0;
if (listeners.fn) return 1;
return listeners.length;
};
/**
* Calls each of the listeners registered for a given event.
*
* @param {(String|Symbol)} event The event name.
* @returns {Boolean} `true` if the event had listeners, else `false`.
* @public
*/
EventEmitter.prototype.emit = function emit(event, a1, a2, a3, a4, a5) {
var evt = prefix ? prefix + event : event;
if (!this._events[evt]) return false;
var listeners = this._events[evt]
, len = arguments.length
, args
, i;
if (listeners.fn) {
if (listeners.once) this.removeListener(event, listeners.fn, undefined, true);
switch (len) {
case 1: return listeners.fn.call(listeners.context), true;
case 2: return listeners.fn.call(listeners.context, a1), true;
case 3: return listeners.fn.call(listeners.context, a1, a2), true;
case 4: return listeners.fn.call(listeners.context, a1, a2, a3), true;
case 5: return listeners.fn.call(listeners.context, a1, a2, a3, a4), true;
case 6: return listeners.fn.call(listeners.context, a1, a2, a3, a4, a5), true;
}
for (i = 1, args = new Array(len -1); i < len; i++) {
args[i - 1] = arguments[i];
}
listeners.fn.apply(listeners.context, args);
} else {
var length = listeners.length
, j;
for (i = 0; i < length; i++) {
if (listeners[i].once) this.removeListener(event, listeners[i].fn, undefined, true);
switch (len) {
case 1: listeners[i].fn.call(listeners[i].context); break;
case 2: listeners[i].fn.call(listeners[i].context, a1); break;
case 3: listeners[i].fn.call(listeners[i].context, a1, a2); break;
case 4: listeners[i].fn.call(listeners[i].context, a1, a2, a3); break;
default:
if (!args) for (j = 1, args = new Array(len -1); j < len; j++) {
args[j - 1] = arguments[j];
}
listeners[i].fn.apply(listeners[i].context, args);
}
}
}
return true;
};
/**
* Add a listener for a given event.
*
* @param {(String|Symbol)} event The event name.
* @param {Function} fn The listener function.
* @param {*} [context=this] The context to invoke the listener with.
* @returns {EventEmitter} `this`.
* @public
*/
EventEmitter.prototype.on = function on(event, fn, context) {
return addListener(this, event, fn, context, false);
};
/**
* Add a one-time listener for a given event.
*
* @param {(String|Symbol)} event The event name.
* @param {Function} fn The listener function.
* @param {*} [context=this] The context to invoke the listener with.
* @returns {EventEmitter} `this`.
* @public
*/
EventEmitter.prototype.once = function once(event, fn, context) {
return addListener(this, event, fn, context, true);
};
/**
* Remove the listeners of a given event.
*
* @param {(String|Symbol)} event The event name.
* @param {Function} fn Only remove the listeners that match this function.
* @param {*} context Only remove the listeners that have this context.
* @param {Boolean} once Only remove one-time listeners.
* @returns {EventEmitter} `this`.
* @public
*/
EventEmitter.prototype.removeListener = function removeListener(event, fn, context, once) {
var evt = prefix ? prefix + event : event;
if (!this._events[evt]) return this;
if (!fn) {
clearEvent(this, evt);
return this;
}
var listeners = this._events[evt];
if (listeners.fn) {
if (
listeners.fn === fn &&
(!once || listeners.once) &&
(!context || listeners.context === context)
) {
clearEvent(this, evt);
}
} else {
for (var i = 0, events = [], length = listeners.length; i < length; i++) {
if (
listeners[i].fn !== fn ||
(once && !listeners[i].once) ||
(context && listeners[i].context !== context)
) {
events.push(listeners[i]);
}
}
//
// Reset the array, or remove it completely if we have no more listeners.
//
if (events.length) this._events[evt] = events.length === 1 ? events[0] : events;
else clearEvent(this, evt);
}
return this;
};
/**
* Remove all listeners, or those of the specified event.
*
* @param {(String|Symbol)} [event] The event name.
* @returns {EventEmitter} `this`.
* @public
*/
EventEmitter.prototype.removeAllListeners = function removeAllListeners(event) {
var evt;
if (event) {
evt = prefix ? prefix + event : event;
if (this._events[evt]) clearEvent(this, evt);
} else {
this._events = new Events();
this._eventsCount = 0;
}
return this;
};
//
// Alias methods names because people roll like that.
//
EventEmitter.prototype.off = EventEmitter.prototype.removeListener;
EventEmitter.prototype.addListener = EventEmitter.prototype.on;
//
// Expose the prefix.
//
EventEmitter.prefixed = prefix;
//
// Allow `EventEmitter` to be imported as module namespace.
//
EventEmitter.EventEmitter = EventEmitter;
//
// Expose the module.
//
if ('undefined' !== 'object') {
module.exports = EventEmitter;
}
} (eventemitter3$1));
var eventemitter3Exports = eventemitter3$1.exports;
var EventEmitter = /*@__PURE__*/getDefaultExportFromCjs(eventemitter3Exports);
var r={grad:.9,turn:360,rad:360/(2*Math.PI)},t=function(r){return "string"==typeof r?r.length>0:"number"==typeof r},n=function(r,t,n){return void 0===t&&(t=0),void 0===n&&(n=Math.pow(10,t)),Math.round(n*r)/n+0},e=function(r,t,n){return void 0===t&&(t=0),void 0===n&&(n=1),r>n?n:r>t?r:t},u=function(r){return (r=isFinite(r)?r%360:0)>0?r:r+360},a=function(r){return {r:e(r.r,0,255),g:e(r.g,0,255),b:e(r.b,0,255),a:e(r.a)}},o=function(r){return {r:n(r.r),g:n(r.g),b:n(r.b),a:n(r.a,3)}},i=/^#([0-9a-f]{3,8})$/i,s=function(r){var t=r.toString(16);return t.length<2?"0"+t:t},h=function(r){var t=r.r,n=r.g,e=r.b,u=r.a,a=Math.max(t,n,e),o=a-Math.min(t,n,e),i=o?a===t?(n-e)/o:a===n?2+(e-t)/o:4+(t-n)/o:0;return {h:60*(i<0?i+6:i),s:a?o/a*100:0,v:a/255*100,a:u}},b=function(r){var t=r.h,n=r.s,e=r.v,u=r.a;t=t/360*6,n/=100,e/=100;var a=Math.floor(t),o=e*(1-n),i=e*(1-(t-a)*n),s=e*(1-(1-t+a)*n),h=a%6;return {r:255*[e,i,o,o,s,e][h],g:255*[s,e,e,i,o,o][h],b:255*[o,o,s,e,e,i][h],a:u}},g=function(r){return {h:u(r.h),s:e(r.s,0,100),l:e(r.l,0,100),a:e(r.a)}},d=function(r){return {h:n(r.h),s:n(r.s),l:n(r.l),a:n(r.a,3)}},f=function(r){return b((n=(t=r).s,{h:t.h,s:(n*=((e=t.l)<50?e:100-e)/100)>0?2*n/(e+n)*100:0,v:e+n,a:t.a}));var t,n,e;},c=function(r){return {h:(t=h(r)).h,s:(u=(200-(n=t.s))*(e=t.v)/100)>0&&u<200?n*e/100/(u<=100?u:200-u)*100:0,l:u/2,a:t.a};var t,n,e,u;},l=/^hsla?\(\s*([+-]?\d*\.?\d+)(deg|rad|grad|turn)?\s*,\s*([+-]?\d*\.?\d+)%\s*,\s*([+-]?\d*\.?\d+)%\s*(?:,\s*([+-]?\d*\.?\d+)(%)?\s*)?\)$/i,p=/^hsla?\(\s*([+-]?\d*\.?\d+)(deg|rad|grad|turn)?\s+([+-]?\d*\.?\d+)%\s+([+-]?\d*\.?\d+)%\s*(?:\/\s*([+-]?\d*\.?\d+)(%)?\s*)?\)$/i,v=/^rgba?\(\s*([+-]?\d*\.?\d+)(%)?\s*,\s*([+-]?\d*\.?\d+)(%)?\s*,\s*([+-]?\d*\.?\d+)(%)?\s*(?:,\s*([+-]?\d*\.?\d+)(%)?\s*)?\)$/i,m=/^rgba?\(\s*([+-]?\d*\.?\d+)(%)?\s+([+-]?\d*\.?\d+)(%)?\s+([+-]?\d*\.?\d+)(%)?\s*(?:\/\s*([+-]?\d*\.?\d+)(%)?\s*)?\)$/i,y={string:[[function(r){var t=i.exec(r);return t?(r=t[1]).length<=4?{r:parseInt(r[0]+r[0],16),g:parseInt(r[1]+r[1],16),b:parseInt(r[2]+r[2],16),a:4===r.length?n(parseInt(r[3]+r[3],16)/255,2):1}:6===r.length||8===r.length?{r:parseInt(r.substr(0,2),16),g:parseInt(r.substr(2,2),16),b:parseInt(r.substr(4,2),16),a:8===r.length?n(parseInt(r.substr(6,2),16)/255,2):1}:null:null},"hex"],[function(r){var t=v.exec(r)||m.exec(r);return t?t[2]!==t[4]||t[4]!==t[6]?null:a({r:Number(t[1])/(t[2]?100/255:1),g:Number(t[3])/(t[4]?100/255:1),b:Number(t[5])/(t[6]?100/255:1),a:void 0===t[7]?1:Number(t[7])/(t[8]?100:1)}):null},"rgb"],[function(t){var n=l.exec(t)||p.exec(t);if(!n)return null;var e,u,a=g({h:(e=n[1],u=n[2],void 0===u&&(u="deg"),Number(e)*(r[u]||1)),s:Number(n[3]),l:Number(n[4]),a:void 0===n[5]?1:Number(n[5])/(n[6]?100:1)});return f(a)},"hsl"]],object:[[function(r){var n=r.r,e=r.g,u=r.b,o=r.a,i=void 0===o?1:o;return t(n)&&t(e)&&t(u)?a({r:Number(n),g:Number(e),b:Number(u),a:Number(i)}):null},"rgb"],[function(r){var n=r.h,e=r.s,u=r.l,a=r.a,o=void 0===a?1:a;if(!t(n)||!t(e)||!t(u))return null;var i=g({h:Number(n),s:Number(e),l:Number(u),a:Number(o)});return f(i)},"hsl"],[function(r){var n=r.h,a=r.s,o=r.v,i=r.a,s=void 0===i?1:i;if(!t(n)||!t(a)||!t(o))return null;var h=function(r){return {h:u(r.h),s:e(r.s,0,100),v:e(r.v,0,100),a:e(r.a)}}({h:Number(n),s:Number(a),v:Number(o),a:Number(s)});return b(h)},"hsv"]]},N=function(r,t){for(var n=0;n<t.length;n++){var e=t[n][0](r);if(e)return [e,t[n][1]]}return [null,void 0]},x=function(r){return "string"==typeof r?N(r.trim(),y.string):"object"==typeof r&&null!==r?N(r,y.object):[null,void 0]},I=function(r){return x(r)[1]},M=function(r,t){var n=c(r);return {h:n.h,s:e(n.s+100*t,0,100),l:n.l,a:n.a}},H=function(r){return (299*r.r+587*r.g+114*r.b)/1e3/255},$=function(r,t){var n=c(r);return {h:n.h,s:n.s,l:e(n.l+100*t,0,100),a:n.a}},j=function(){function r(r){this.parsed=x(r)[0],this.rgba=this.parsed||{r:0,g:0,b:0,a:1};}return r.prototype.isValid=function(){return null!==this.parsed},r.prototype.brightness=function(){return n(H(this.rgba),2)},r.prototype.isDark=function(){return H(this.rgba)<.5},r.prototype.isLight=function(){return H(this.rgba)>=.5},r.prototype.toHex=function(){return r=o(this.rgba),t=r.r,e=r.g,u=r.b,i=(a=r.a)<1?s(n(255*a)):"","#"+s(t)+s(e)+s(u)+i;var r,t,e,u,a,i;},r.prototype.toRgb=function(){return o(this.rgba)},r.prototype.toRgbString=function(){return r=o(this.rgba),t=r.r,n=r.g,e=r.b,(u=r.a)<1?"rgba("+t+", "+n+", "+e+", "+u+")":"rgb("+t+", "+n+", "+e+")";var r,t,n,e,u;},r.prototype.toHsl=function(){return d(c(this.rgba))},r.prototype.toHslString=function(){return r=d(c(this.rgba)),t=r.h,n=r.s,e=r.l,(u=r.a)<1?"hsla("+t+", "+n+"%, "+e+"%, "+u+")":"hsl("+t+", "+n+"%, "+e+"%)";var r,t,n,e,u;},r.prototype.toHsv=function(){return r=h(this.rgba),{h:n(r.h),s:n(r.s),v:n(r.v),a:n(r.a,3)};var r;},r.prototype.invert=function(){return w({r:255-(r=this.rgba).r,g:255-r.g,b:255-r.b,a:r.a});var r;},r.prototype.saturate=function(r){return void 0===r&&(r=.1),w(M(this.rgba,r))},r.prototype.desaturate=function(r){return void 0===r&&(r=.1),w(M(this.rgba,-r))},r.prototype.grayscale=function(){return w(M(this.rgba,-1))},r.prototype.lighten=function(r){return void 0===r&&(r=.1),w($(this.rgba,r))},r.prototype.darken=function(r){return void 0===r&&(r=.1),w($(this.rgba,-r))},r.prototype.rotate=function(r){return void 0===r&&(r=15),this.hue(this.hue()+r)},r.prototype.alpha=function(r){return "number"==typeof r?w({r:(t=this.rgba).r,g:t.g,b:t.b,a:r}):n(this.rgba.a,3);var t;},r.prototype.hue=function(r){var t=c(this.rgba);return "number"==typeof r?w({h:r,s:t.s,l:t.l,a:t.a}):n(t.h)},r.prototype.isEqual=function(r){return this.toHex()===w(r).toHex()},r}(),w=function(r){return r instanceof j?r:new j(r)},S=[],k=function(r){r.forEach(function(r){S.indexOf(r)<0&&(r(j,y),S.push(r));});},E=function(){return new j({r:255*Math.random(),g:255*Math.random(),b:255*Math.random()})};
function namesPlugin(e,f){var a={white:"#ffffff",bisque:"#ffe4c4",blue:"#0000ff",cadetblue:"#5f9ea0",chartreuse:"#7fff00",chocolate:"#d2691e",coral:"#ff7f50",antiquewhite:"#faebd7",aqua:"#00ffff",azure:"#f0ffff",whitesmoke:"#f5f5f5",papayawhip:"#ffefd5",plum:"#dda0dd",blanchedalmond:"#ffebcd",black:"#000000",gold:"#ffd700",goldenrod:"#daa520",gainsboro:"#dcdcdc",cornsilk:"#fff8dc",cornflowerblue:"#6495ed",burlywood:"#deb887",aquamarine:"#7fffd4",beige:"#f5f5dc",crimson:"#dc143c",cyan:"#00ffff",darkblue:"#00008b",darkcyan:"#008b8b",darkgoldenrod:"#b8860b",darkkhaki:"#bdb76b",darkgray:"#a9a9a9",darkgreen:"#006400",darkgrey:"#a9a9a9",peachpuff:"#ffdab9",darkmagenta:"#8b008b",darkred:"#8b0000",darkorchid:"#9932cc",darkorange:"#ff8c00",darkslateblue:"#483d8b",gray:"#808080",darkslategray:"#2f4f4f",darkslategrey:"#2f4f4f",deeppink:"#ff1493",deepskyblue:"#00bfff",wheat:"#f5deb3",firebrick:"#b22222",floralwhite:"#fffaf0",ghostwhite:"#f8f8ff",darkviolet:"#9400d3",magenta:"#ff00ff",green:"#008000",dodgerblue:"#1e90ff",grey:"#808080",honeydew:"#f0fff0",hotpink:"#ff69b4",blueviolet:"#8a2be2",forestgreen:"#228b22",lawngreen:"#7cfc00",indianred:"#cd5c5c",indigo:"#4b0082",fuchsia:"#ff00ff",brown:"#a52a2a",maroon:"#800000",mediumblue:"#0000cd",lightcoral:"#f08080",darkturquoise:"#00ced1",lightcyan:"#e0ffff",ivory:"#fffff0",lightyellow:"#ffffe0",lightsalmon:"#ffa07a",lightseagreen:"#20b2aa",linen:"#faf0e6",mediumaquamarine:"#66cdaa",lemonchiffon:"#fffacd",lime:"#00ff00",khaki:"#f0e68c",mediumseagreen:"#3cb371",limegreen:"#32cd32",mediumspringgreen:"#00fa9a",lightskyblue:"#87cefa",lightblue:"#add8e6",midnightblue:"#191970",lightpink:"#ffb6c1",mistyrose:"#ffe4e1",moccasin:"#ffe4b5",mintcream:"#f5fffa",lightslategray:"#778899",lightslategrey:"#778899",navajowhite:"#ffdead",navy:"#000080",mediumvioletred:"#c71585",powderblue:"#b0e0e6",palegoldenrod:"#eee8aa",oldlace:"#fdf5e6",paleturquoise:"#afeeee",mediumturquoise:"#48d1cc",mediumorchid:"#ba55d3",rebeccapurple:"#663399",lightsteelblue:"#b0c4de",mediumslateblue:"#7b68ee",thistle:"#d8bfd8",tan:"#d2b48c",orchid:"#da70d6",mediumpurple:"#9370db",purple:"#800080",pink:"#ffc0cb",skyblue:"#87ceeb",springgreen:"#00ff7f",palegreen:"#98fb98",red:"#ff0000",yellow:"#ffff00",slateblue:"#6a5acd",lavenderblush:"#fff0f5",peru:"#cd853f",palevioletred:"#db7093",violet:"#ee82ee",teal:"#008080",slategray:"#708090",slategrey:"#708090",aliceblue:"#f0f8ff",darkseagreen:"#8fbc8f",darkolivegreen:"#556b2f",greenyellow:"#adff2f",seagreen:"#2e8b57",seashell:"#fff5ee",tomato:"#ff6347",silver:"#c0c0c0",sienna:"#a0522d",lavender:"#e6e6fa",lightgreen:"#90ee90",orange:"#ffa500",orangered:"#ff4500",steelblue:"#4682b4",royalblue:"#4169e1",turquoise:"#40e0d0",yellowgreen:"#9acd32",salmon:"#fa8072",saddlebrown:"#8b4513",sandybrown:"#f4a460",rosybrown:"#bc8f8f",darksalmon:"#e9967a",lightgoldenrodyellow:"#fafad2",snow:"#fffafa",lightgrey:"#d3d3d3",lightgray:"#d3d3d3",dimgray:"#696969",dimgrey:"#696969",olivedrab:"#6b8e23",olive:"#808000"},r={};for(var d in a)r[a[d]]=d;var l={};e.prototype.toName=function(f){if(!(this.rgba.a||this.rgba.r||this.rgba.g||this.rgba.b))return "transparent";var d,i,n=r[this.toHex()];if(n)return n;if(null==f?void 0:f.closest){var o=this.toRgb(),t=1/0,b="black";if(!l.length)for(var c in a)l[c]=new e(a[c]).toRgb();for(var g in a){var u=(d=o,i=l[g],Math.pow(d.r-i.r,2)+Math.pow(d.g-i.g,2)+Math.pow(d.b-i.b,2));u<t&&(t=u,b=g);}return b}};f.string.push([function(f){var r=f.toLowerCase(),d="transparent"===r?"#0000":a[r];return d?new e(d).toRgb():null},"name"]);}
"use strict";
var __defProp$1c = Object.defineProperty;
var __getOwnPropSymbols$1c = Object.getOwnPropertySymbols;
var __hasOwnProp$1c = Object.prototype.hasOwnProperty;
var __propIsEnum$1c = Object.prototype.propertyIsEnumerable;
var __defNormalProp$1c = (obj, key, value) => key in obj ? __defProp$1c(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __spreadValues$1c = (a, b) => {
for (var prop in b || (b = {}))
if (__hasOwnProp$1c.call(b, prop))
__defNormalProp$1c(a, prop, b[prop]);
if (__getOwnPropSymbols$1c)
for (var prop of __getOwnPropSymbols$1c(b)) {
if (__propIsEnum$1c.call(b, prop))
__defNormalProp$1c(a, prop, b[prop]);
}
return a;
};
k([namesPlugin]);
const _Color = class _Color {
/**
* @param {ColorSource} value - Optional value to use, if not provided, white is used.
*/
constructor(value = 16777215) {
this._value = null;
this._components = new Float32Array(4);
this._components.fill(1);
this._int = 16777215;
this.value = value;
}
/**
* Get the red component of the color, normalized between 0 and 1.
* @example
* ```ts
* const color = new Color('red');
* console.log(color.red); // 1
*
* const green = new Color('#00ff00');
* console.log(green.red); // 0
* ```
*/
get red() {
return this._components[0];
}
/**
* Get the green component of the color, normalized between 0 and 1.
* @example
* ```ts
* const color = new Color('lime');
* console.log(color.green); // 1
*
* const red = new Color('#ff0000');
* console.log(red.green); // 0
* ```
*/
get green() {
return this._components[1];
}
/**
* Get the blue component of the color, normalized between 0 and 1.
* @example
* ```ts
* const color = new Color('blue');
* console.log(color.blue); // 1
*
* const yellow = new Color('#ffff00');
* console.log(yellow.blue); // 0
* ```
*/
get blue() {
return this._components[2];
}
/**
* Get the alpha component of the color, normalized between 0 and 1.
* @example
* ```ts
* const color = new Color('red');
* console.log(color.alpha); // 1 (fully opaque)
*
* const transparent = new Color('rgba(255, 0, 0, 0.5)');
* console.log(transparent.alpha); // 0.5 (semi-transparent)
* ```
*/
get alpha() {
return this._components[3];
}
/**
* Sets the color value and returns the instance for chaining.
*
* This is a chainable version of setting the `value` property.
* @param value - The color to set. Accepts various formats:
* - Hex strings/numbers (e.g., '#ff0000', 0xff0000)
* - RGB/RGBA values (arrays, objects)
* - CSS color names
* - HSL/HSLA values
* - HSV/HSVA values
* @returns The Color instance for chaining
* @example
* ```ts
* // Basic usage
* const color = new Color();
* color.setValue('#ff0000')
* .setAlpha(0.5)
* .premultiply(0.8);
*
* // Different formats
* color.setValue(0xff0000); // Hex number
* color.setValue('#ff0000'); // Hex string
* color.setValue([1, 0, 0]); // RGB array
* color.setValue([1, 0, 0, 0.5]); // RGBA array
* color.setValue({ r: 1, g: 0, b: 0 }); // RGB object
*
* // Copy from another color
* const red = new Color('red');
* color.setValue(red);
* ```
* @throws {Error} If the color value is invalid or null
* @see {@link Color.value} For the underlying value property
*/
setValue(value) {
this.value = value;
return this;
}
/**
* The current color source. This property allows getting and setting the color value
* while preserving the original format where possible.
* @remarks
* When setting:
* - Setting to a `Color` instance copies its source and components
* - Setting to other valid sources normalizes and stores the value
* - Setting to `null` throws an Error
* - The color remains unchanged if normalization fails
*
* When getting:
* - Returns `null` if color was modified by {@link Color.multiply} or {@link Color.premultiply}
* - Otherwise returns the original color source
* @example
* ```ts
* // Setting different color formats
* const color = new Color();
*
* color.value = 0xff0000; // Hex number
* color.value = '#ff0000'; // Hex string
* color.value = [1, 0, 0]; // RGB array
* color.value = [1, 0, 0, 0.5]; // RGBA array
* color.value = { r: 1, g: 0, b: 0 }; // RGB object
*
* // Copying from another color
* const red = new Color('red');
* color.value = red; // Copies red's components
*
* // Getting the value
* console.log(color.value); // Returns original format
*
* // After modifications
* color.multiply([0.5, 0.5, 0.5]);
* console.log(color.value); // Returns null
* ```
* @throws {Error} When attempting to set `null`
*/
set value(value) {
if (value instanceof _Color) {
this._value = this._cloneSource(value._value);
this._int = value._int;
this._components.set(value._components);
} else if (value === null) {
throw new Error("Cannot set Color#value to null");
} else if (this._value === null || !this._isSourceEqual(this._value, value)) {
this._value = this._cloneSource(value);
this._normalize(this._value);
}
}
get value() {
return this._value;
}
/**
* Copy a color source internally.
* @param value - Color source
*/
_cloneSource(value) {
if (typeof value === "string" || typeof value === "number" || value instanceof Number || value === null) {
return value;
} else if (Array.isArray(value) || ArrayBuffer.isView(value)) {
return value.slice(0);
} else if (typeof value === "object" && value !== null) {
return __spreadValues$1c({}, value);
}
return value;
}
/**
* Equality check for color sources.
* @param value1 - First color source
* @param value2 - Second color source
* @returns `true` if the color sources are equal, `false` otherwise.
*/
_isSourceEqual(value1, value2) {
const type1 = typeof value1;
const type2 = typeof value2;
if (type1 !== type2) {
return false;
} else if (type1 === "number" || type1 === "string" || value1 instanceof Number) {
return value1 === value2;
} else if (Array.isArray(value1) && Array.isArray(value2) || ArrayBuffer.isView(value1) && ArrayBuffer.isView(value2)) {
if (value1.length !== value2.length) {
return false;
}
return value1.every((v, i) => v === value2[i]);
} else if (value1 !== null && value2 !== null) {
const keys1 = Object.keys(value1);
const keys2 = Object.keys(value2);
if (keys1.length !== keys2.length) {
return false;
}
return keys1.every((key) => value1[key] === value2[key]);
}
return value1 === value2;
}
/**
* Convert to a RGBA color object with normalized components (0-1).
* @example
* ```ts
* import { Color } from 'pixi.js';
*
* // Convert colors to RGBA objects
* new Color('white').toRgba(); // returns { r: 1, g: 1, b: 1, a: 1 }
* new Color('#ff0000').toRgba(); // returns { r: 1, g: 0, b: 0, a: 1 }
*
* // With transparency
* new Color('rgba(255,0,0,0.5)').toRgba(); // returns { r: 1, g: 0, b: 0, a: 0.5 }
* ```
* @returns An RGBA object with normalized components
*/
toRgba() {
const [r, g, b, a] = this._components;
return { r, g, b, a };
}
/**
* Convert to a RGB color object with normalized components (0-1).
*
* Alpha component is omitted in the output.
* @example
* ```ts
* import { Color } from 'pixi.js';
*
* // Convert colors to RGB objects
* new Color('white').toRgb(); // returns { r: 1, g: 1, b: 1 }
* new Color('#ff0000').toRgb(); // returns { r: 1, g: 0, b: 0 }
*
* // Alpha is ignored
* new Color('rgba(255,0,0,0.5)').toRgb(); // returns { r: 1, g: 0, b: 0 }
* ```
* @returns An RGB object with normalized components
*/
toRgb() {
const [r, g, b] = this._components;
return { r, g, b };
}
/**
* Convert to a CSS-style rgba string representation.
*
* RGB components are scaled to 0-255 range, alpha remains 0-1.
* @example
* ```ts
* import { Color } from 'pixi.js';
*
* // Convert colors to RGBA strings
* new Color('white').toRgbaString(); // returns "rgba(255,255,255,1)"
* new Color('#ff0000').toRgbaString(); // returns "rgba(255,0,0,1)"
*
* // With transparency
* new Color([1, 0, 0, 0.5]).toRgbaString(); // returns "rgba(255,0,0,0.5)"
* ```
* @returns A CSS-compatible rgba string
*/
toRgbaString() {
const [r, g, b] = this.toUint8RgbArray();
return `rgba(${r},${g},${b},${this.alpha})`;
}
/**
* Convert to an [R, G, B] array of clamped uint8 values (0 to 255).
* @param {number[]|Uint8Array|Uint8ClampedArray} [out] - Optional output array. If not provided,
* a cached array will be used and returned.
* @returns Array containing RGB components as integers between 0-255
* @example
* ```ts
* // Basic usage
* new Color('white').toUint8RgbArray(); // returns [255, 255, 255]
* new Color('#ff0000').toUint8RgbArray(); // returns [255, 0, 0]
*
* // Using custom output array
* const rgb = new Uint8Array(3);
* new Color('blue').toUint8RgbArray(rgb); // rgb is now [0, 0, 255]
*
* // Using different array types
* new Color('red').toUint8RgbArray(new Uint8ClampedArray(3)); // [255, 0, 0]
* new Color('red').toUint8RgbArray([]); // [255, 0, 0]
* ```
* @remarks
* - Output values are always clamped between 0-255
* - Alpha component is not included in output
* - Reuses internal cache array if no output array provided
*/
toUint8RgbArray(out) {
const [r, g, b] = this._components;
if (!this._arrayRgb) {
this._arrayRgb = [];
}
out || (out = this._arrayRgb);
out[0] = Math.round(r * 255);
out[1] = Math.round(g * 255);
out[2] = Math.round(b * 255);
return out;
}
/**
* Convert to an [R, G, B, A] array of normalized floats (numbers from 0.0 to 1.0).
* @param {number[]|Float32Array} [out] - Optional output array. If not provided,
* a cached array will be used and returned.
* @returns Array containing RGBA components as floats between 0-1
* @example
* ```ts
* // Basic usage
* new Color('white').toArray(); // returns [1, 1, 1, 1]
* new Color('red').toArray(); // returns [1, 0, 0, 1]
*
* // With alpha
* new Color('rgba(255,0,0,0.5)').toArray(); // returns [1, 0, 0, 0.5]
*
* // Using custom output array
* const rgba = new Float32Array(4);
* new Color('blue').toArray(rgba); // rgba is now [0, 0, 1, 1]
* ```
* @remarks
* - Output values are normalized between 0-1
* - Includes alpha component as the fourth value
* - Reuses internal cache array if no output array provided
*/
toArray(out) {
if (!this._arrayRgba) {
this._arrayRgba = [];
}
out || (out = this._arrayRgba);
const [r, g, b, a] = this._components;
out[0] = r;
out[1] = g;
out[2] = b;
out[3] = a;
return out;
}
/**
* Convert to an [R, G, B] array of normalized floats (numbers from 0.0 to 1.0).
* @param {number[]|Float32Array} [out] - Optional output array. If not provided,
* a cached array will be used and returned.
* @returns Array containing RGB components as floats between 0-1
* @example
* ```ts
* // Basic usage
* new Color('white').toRgbArray(); // returns [1, 1, 1]
* new Color('red').toRgbArray(); // returns [1, 0, 0]
*
* // Using custom output array
* const rgb = new Float32Array(3);
* new Color('blue').toRgbArray(rgb); // rgb is now [0, 0, 1]
* ```
* @remarks
* - Output values are normalized between 0-1
* - Alpha component is omitted from output
* - Reuses internal cache array if no output array provided
*/
toRgbArray(out) {
if (!this._arrayRgb) {
this._arrayRgb = [];
}
out || (out = this._arrayRgb);
const [r, g, b] = this._components;
out[0] = r;
out[1] = g;
out[2] = b;
return out;
}
/**
* Convert to a hexadecimal number.
* @returns The color as a 24-bit RGB integer
* @example
* ```ts
* // Basic usage
* new Color('white').toNumber(); // returns 0xffffff
* new Color('red').toNumber(); // returns 0xff0000
*
* // Store as hex
* const color = new Color('blue');
* const hex = color.toNumber(); // 0x0000ff
* ```
*/
toNumber() {
return this._int;
}
/**
* Convert to a BGR number.
*
* Useful for platforms that expect colors in BGR format.
* @returns The color as a 24-bit BGR integer
* @example
* ```ts
* // Convert RGB to BGR
* new Color(0xffcc99).toBgrNumber(); // returns 0x99ccff
*
* // Common use case: platform-specific color format
* const color = new Color('orange');
* const bgrColor = color.toBgrNumber(); // Color with swapped R/B channels
* ```
* @remarks
* This swaps the red and blue channels compared to the normal RGB format:
* - RGB 0xRRGGBB becomes BGR 0xBBGGRR
*/
toBgrNumber() {
const [r, g, b] = this.toUint8RgbArray();
return (b << 16) + (g << 8) + r;
}
/**
* Convert to a hexadecimal number in little endian format (e.g., BBGGRR).
*
* Useful for platforms that expect colors in little endian byte order.
* @example
* ```ts
* import { Color } from 'pixi.js';
*
* // Convert RGB color to little endian format
* new Color(0xffcc99).toLittleEndianNumber(); // returns 0x99ccff
*
* // Common use cases:
* const color = new Color('orange');
* const leColor = color.toLittleEndianNumber(); // Swaps byte order for LE systems
*
* // Multiple conversions
* const colors = {
* normal: 0xffcc99,
* littleEndian: new Color(0xffcc99).toLittleEndianNumber(), // 0x99ccff
* backToNormal: new Color(0x99ccff).toLittleEndianNumber() // 0xffcc99
* };
* ```
* @remarks
* - Swaps R and B channels in the color value
* - RGB 0xRRGGBB becomes 0xBBGGRR
* - Useful for systems that use little endian byte order
* - Can be used to convert back and forth between formats
* @returns The color as a number in little endian format (BBGGRR)
* @see {@link Color.toBgrNumber} For BGR format without byte swapping
*/
toLittleEndianNumber() {
const value = this._int;
return (value >> 16) + (value & 65280) + ((value & 255) << 16);
}
/**
* Multiply with another color.
*
* This action is destructive and modifies the original color.
* @param {ColorSource} value - The color to multiply by. Accepts any valid color format:
* - Hex strings/numbers (e.g., '#ff0000', 0xff0000)
* - RGB/RGBA arrays ([1, 0, 0], [1, 0, 0, 1])
* - Color objects ({ r: 1, g: 0, b: 0 })
* - CSS color names ('red', 'blue')
* @returns this - The Color instance for chaining
* @example
* ```ts
* // Basic multiplication
* const color = new Color('#ff0000');
* color.multiply(0x808080); // 50% darker red
*
* // With transparency
* color.multiply([1, 1, 1, 0.5]); // 50% transparent
*
* // Chain operations
* color
* .multiply('#808080')
* .multiply({ r: 1, g: 1, b: 1, a: 0.5 });
* ```
* @remarks
* - Multiplies each RGB component and alpha separately
* - Values are clamped between 0-1
* - Original color format is lost (value becomes null)
* - Operation cannot be undone
*/
multiply(value) {
const [r, g, b, a] = _Color._temp.setValue(value)._components;
this._components[0] *= r;
this._components[1] *= g;
this._components[2] *= b;
this._components[3] *= a;
this._refreshInt();
this._value = null;
return this;
}
/**
* Converts color to a premultiplied alpha format.
*
* This action is destructive and modifies the original color.
* @param alpha - The alpha value to multiply by (0-1)
* @param {boolean} [applyToRGB=true] - Whether to premultiply RGB channels
* @returns {Color} The Color instance for chaining
* @example
* ```ts
* // Basic premultiplication
* const color = new Color('red');
* color.premultiply(0.5); // 50% transparent red with premultiplied RGB
*
* // Alpha only (RGB unchanged)
* color.premultiply(0.5, false); // 50% transparent, original RGB
*
* // Chain with other operations
* color
* .multiply(0x808080)
* .premultiply(0.5)
* .toNumber();
* ```
* @remarks
* - RGB channels are multiplied by alpha when applyToRGB is true
* - Alpha is always set to the provided value
* - Values are clamped between 0-1
* - Original color format is lost (value becomes null)
* - Operation cannot be undone
*/
premultiply(alpha, applyToRGB = true) {
if (applyToRGB) {
this._components[0] *= alpha;
this._components[1] *= alpha;
this._components[2] *= alpha;
}
this._components[3] = alpha;
this._refreshInt();
this._value = null;
return this;
}
/**
* Returns the color as a 32-bit premultiplied alpha integer.
*
* Format: 0xAARRGGBB
* @param {number} alpha - The alpha value to multiply by (0-1)
* @param {boolean} [applyToRGB=true] - Whether to premultiply RGB channels
* @returns {number} The premultiplied color as a 32-bit integer
* @example
* ```ts
* // Convert to premultiplied format
* const color = new Color('red');
*
* // Full opacity (0xFFRRGGBB)
* color.toPremultiplied(1.0); // 0xFFFF0000
*
* // 50% transparency with premultiplied RGB
* color.toPremultiplied(0.5); // 0x7F7F0000
*
* // 50% transparency without RGB premultiplication
* color.toPremultiplied(0.5, false); // 0x7FFF0000
* ```
* @remarks
* - Returns full opacity (0xFF000000) when alpha is 1.0
* - Returns 0 when alpha is 0.0 and applyToRGB is true
* - RGB values are rounded during premultiplication
*/
toPremultiplied(alpha, applyToRGB = true) {
if (alpha === 1) {
return (255 << 24) + this._int;
}
if (alpha === 0) {
return applyToRGB ? 0 : this._int;
}
let r = this._int >> 16 & 255;
let g = this._int >> 8 & 255;
let b = this._int & 255;
if (applyToRGB) {
r = r * alpha + 0.5 | 0;
g = g * alpha + 0.5 | 0;
b = b * alpha + 0.5 | 0;
}
return (alpha * 255 << 24) + (r << 16) + (g << 8) + b;
}
/**
* Convert to a hexadecimal string (6 characters).
* @returns A CSS-compatible hex color string (e.g., "#ff0000")
* @example
* ```ts
* import { Color } from 'pixi.js';
*
* // Basic colors
* new Color('red').toHex(); // returns "#ff0000"
* new Color('white').toHex(); // returns "#ffffff"
* new Color('black').toHex(); // returns "#000000"
*
* // From different formats
* new Color(0xff0000).toHex(); // returns "#ff0000"
* new Color([1, 0, 0]).toHex(); // returns "#ff0000"
* new Color({ r: 1, g: 0, b: 0 }).toHex(); // returns "#ff0000"
* ```
* @remarks
* - Always returns a 6-character hex string
* - Includes leading "#" character
* - Alpha channel is ignored
* - Values are rounded to nearest hex value
*/
toHex() {
const hexString = this._int.toString(16);
return `#${"000000".substring(0, 6 - hexString.length) + hexString}`;
}
/**