UNPKG

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">

235 lines (231 loc) 7.49 kB
'use strict'; var Color = require('../../../../color/Color.js'); var adapter = require('../../../../environment/adapter.js'); var Matrix = require('../../../../maths/matrix/Matrix.js'); var ImageSource = require('../../../../rendering/renderers/shared/texture/sources/ImageSource.js'); var Texture = require('../../../../rendering/renderers/shared/texture/Texture.js'); var uid = require('../../../../utils/data/uid.js'); var deprecation = require('../../../../utils/logging/deprecation.js'); var definedProps = require('../../../container/utils/definedProps.js'); "use strict"; const emptyColorStops = [{ offset: 0, color: "white" }, { offset: 1, color: "black" }]; const _FillGradient = class _FillGradient { constructor(...args) { /** * Unique identifier for this gradient instance * @internal */ this.uid = uid.uid("fillGradient"); /** Type of gradient - currently only supports 'linear' */ this.type = "linear"; /** Array of color stops defining the gradient */ this.colorStops = []; let options = ensureGradientOptions(args); const defaults = options.type === "radial" ? _FillGradient.defaultRadialOptions : _FillGradient.defaultLinearOptions; options = { ...defaults, ...definedProps.definedProps(options) }; this._textureSize = options.textureSize; this._wrapMode = options.wrapMode; if (options.type === "radial") { this.center = options.center; this.outerCenter = options.outerCenter ?? this.center; this.innerRadius = options.innerRadius; this.outerRadius = options.outerRadius; this.scale = options.scale; this.rotation = options.rotation; } else { this.start = options.start; this.end = options.end; } this.textureSpace = options.textureSpace; this.type = options.type; options.colorStops.forEach((stop) => { this.addColorStop(stop.offset, stop.color); }); } /** * Adds a color stop to the gradient * @param offset - Position of the stop (0-1) * @param color - Color of the stop * @returns This gradient instance for chaining */ addColorStop(offset, color) { this.colorStops.push({ offset, color: Color.Color.shared.setValue(color).toHexa() }); return this; } /** * Builds the internal texture and transform for the gradient. * Called automatically when the gradient is first used. * @internal */ buildLinearGradient() { if (this.texture) return; let { x: x0, y: y0 } = this.start; let { x: x1, y: y1 } = this.end; let dx = x1 - x0; let dy = y1 - y0; const flip = dx < 0 || dy < 0; if (this._wrapMode === "clamp-to-edge") { if (dx < 0) { const temp = x0; x0 = x1; x1 = temp; dx *= -1; } if (dy < 0) { const temp = y0; y0 = y1; y1 = temp; dy *= -1; } } const colorStops = this.colorStops.length ? this.colorStops : emptyColorStops; const defaultSize = this._textureSize; const { canvas, context } = getCanvas(defaultSize, 1); const gradient = !flip ? context.createLinearGradient(0, 0, this._textureSize, 0) : context.createLinearGradient(this._textureSize, 0, 0, 0); addColorStops(gradient, colorStops); context.fillStyle = gradient; context.fillRect(0, 0, defaultSize, 1); this.texture = new Texture.Texture({ source: new ImageSource.ImageSource({ resource: canvas, addressMode: this._wrapMode }) }); const dist = Math.sqrt(dx * dx + dy * dy); const angle = Math.atan2(dy, dx); const m = new Matrix.Matrix(); m.scale(dist / defaultSize, 1); m.rotate(angle); m.translate(x0, y0); if (this.textureSpace === "local") { m.scale(defaultSize, defaultSize); } this.transform = m; } /** * Builds the internal texture and transform for the gradient. * Called automatically when the gradient is first used. * @internal */ buildGradient() { if (this.type === "linear") { this.buildLinearGradient(); } else { this.buildRadialGradient(); } } /** * Builds the internal texture and transform for the radial gradient. * Called automatically when the gradient is first used. * @internal */ buildRadialGradient() { if (this.texture) return; const colorStops = this.colorStops.length ? this.colorStops : emptyColorStops; const defaultSize = this._textureSize; const { canvas, context } = getCanvas(defaultSize, defaultSize); const { x: x0, y: y0 } = this.center; const { x: x1, y: y1 } = this.outerCenter; const r0 = this.innerRadius; const r1 = this.outerRadius; const ox = x1 - r1; const oy = y1 - r1; const scale = defaultSize / (r1 * 2); const cx = (x0 - ox) * scale; const cy = (y0 - oy) * scale; const gradient = context.createRadialGradient( cx, cy, r0 * scale, (x1 - ox) * scale, (y1 - oy) * scale, r1 * scale ); addColorStops(gradient, colorStops); context.fillStyle = colorStops[colorStops.length - 1].color; context.fillRect(0, 0, defaultSize, defaultSize); context.fillStyle = gradient; context.translate(cx, cy); context.rotate(this.rotation); context.scale(1, this.scale); context.translate(-cx, -cy); context.fillRect(0, 0, defaultSize, defaultSize); this.texture = new Texture.Texture({ source: new ImageSource.ImageSource({ resource: canvas, addressMode: this._wrapMode }) }); const m = new Matrix.Matrix(); m.scale(1 / scale, 1 / scale); m.translate(ox, oy); if (this.textureSpace === "local") { m.scale(defaultSize, defaultSize); } this.transform = m; } /** * Gets a unique key representing the current state of the gradient. * Used internally for caching. * @returns Unique string key */ get styleKey() { return this.uid; } destroy() { this.texture?.destroy(true); this.texture = null; } }; /** Default options for creating a gradient fill */ _FillGradient.defaultLinearOptions = { start: { x: 0, y: 0 }, end: { x: 0, y: 1 }, colorStops: [], textureSpace: "local", type: "linear", textureSize: 256, wrapMode: "clamp-to-edge" }; /** Default options for creating a radial gradient fill */ _FillGradient.defaultRadialOptions = { center: { x: 0.5, y: 0.5 }, innerRadius: 0, outerRadius: 0.5, colorStops: [], scale: 1, textureSpace: "local", type: "radial", textureSize: 256, wrapMode: "clamp-to-edge" }; let FillGradient = _FillGradient; function addColorStops(gradient, colorStops) { for (let i = 0; i < colorStops.length; i++) { const stop = colorStops[i]; gradient.addColorStop(stop.offset, stop.color); } } function getCanvas(width, height) { const canvas = adapter.DOMAdapter.get().createCanvas(width, height); const context = canvas.getContext("2d"); return { canvas, context }; } function ensureGradientOptions(args) { let options = args[0] ?? {}; if (typeof options === "number" || args[1]) { deprecation.deprecation("8.5.2", `use options object instead`); options = { type: "linear", start: { x: args[0], y: args[1] }, end: { x: args[2], y: args[3] }, textureSpace: args[4], textureSize: args[5] ?? FillGradient.defaultLinearOptions.textureSize }; } return options; } exports.FillGradient = FillGradient; //# sourceMappingURL=FillGradient.js.map