diff --git a/src/core/text/Text.js b/src/core/text/Text.js index babf0f2..1c3c7b3 100644 --- a/src/core/text/Text.js +++ b/src/core/text/Text.js @@ -525,6 +525,29 @@ const width = this.canvas.width / this.resolution; const height = this.canvas.height / this.resolution; + // make a copy of the style settings, so we can manipulate them later + const fill = style.fill.slice(); + const fillGradientStops = style.fillGradientStops.slice(); + + // wanting to evenly distribute the fills. So an array of 4 colours should give fills of 0.25, 0.5 and 0.75 + if (!fillGradientStops.length) + { + const lengthPlus1 = fill.length + 1; + + for (let i = 1; i < lengthPlus1; ++i) + { + fillGradientStops.push(i / lengthPlus1); + } + } + + // stop the bleeding of the last gradient on the line above to the top gradient of the this line + // by hard defining the first gradient colour at point 0, and last gradient colour at point 1 + fill.unshift(style.fill[0]); + fillGradientStops.unshift(0); + + fill.push(style.fill[style.fill.length - 1]); + fillGradientStops.push(1); + if (style.fillGradientType === TEXT_GRADIENT.LINEAR_VERTICAL) { // start the gradient at the top center of the canvas, and end at the bottom middle of the canvas @@ -532,15 +555,22 @@ // we need to repeat the gradient so that each individual line of text has the same vertical gradient effect // ['#FF0000', '#00FF00', '#0000FF'] over 2 lines would create stops at 0.125, 0.25, 0.375, 0.625, 0.75, 0.875 - totalIterations = (style.fill.length + 1) * lines.length; + totalIterations = (fill.length + 1) * lines.length; currentIteration = 0; for (let i = 0; i < lines.length; i++) { currentIteration += 1; - for (let j = 0; j < style.fill.length; j++) + for (let j = 0; j < fill.length; j++) { - stop = (currentIteration / totalIterations); - gradient.addColorStop(stop, style.fill[j]); + if (fillGradientStops[j]) + { + stop = (fillGradientStops[j] / lines.length) + (i / lines.length); + } + else + { + stop = currentIteration / totalIterations; + } + gradient.addColorStop(stop, fill[j]); currentIteration++; } } @@ -552,13 +582,20 @@ // can just evenly space out the gradients in this case, as multiple lines makes no difference // to an even left to right gradient - totalIterations = style.fill.length + 1; + totalIterations = fill.length + 1; currentIteration = 1; - for (let i = 0; i < style.fill.length; i++) + for (let i = 0; i < fill.length; i++) { - stop = currentIteration / totalIterations; - gradient.addColorStop(stop, style.fill[i]); + if (fillGradientStops[i]) + { + stop = fillGradientStops[i]; + } + else + { + stop = currentIteration / totalIterations; + } + gradient.addColorStop(stop, fill[i]); currentIteration++; } } @@ -569,7 +606,7 @@ /** * Destroys this text object. * Note* Unlike a Sprite, a Text object will automatically destroy its baseTexture and texture as - * the majorety of the time the texture will not be shared with any other Sprites. + * the majority of the time the texture will not be shared with any other Sprites. * * @param {object|boolean} [options] - Options parameter. A boolean will act as if all options * have been set to that value diff --git a/src/core/text/Text.js b/src/core/text/Text.js index babf0f2..1c3c7b3 100644 --- a/src/core/text/Text.js +++ b/src/core/text/Text.js @@ -525,6 +525,29 @@ const width = this.canvas.width / this.resolution; const height = this.canvas.height / this.resolution; + // make a copy of the style settings, so we can manipulate them later + const fill = style.fill.slice(); + const fillGradientStops = style.fillGradientStops.slice(); + + // wanting to evenly distribute the fills. So an array of 4 colours should give fills of 0.25, 0.5 and 0.75 + if (!fillGradientStops.length) + { + const lengthPlus1 = fill.length + 1; + + for (let i = 1; i < lengthPlus1; ++i) + { + fillGradientStops.push(i / lengthPlus1); + } + } + + // stop the bleeding of the last gradient on the line above to the top gradient of the this line + // by hard defining the first gradient colour at point 0, and last gradient colour at point 1 + fill.unshift(style.fill[0]); + fillGradientStops.unshift(0); + + fill.push(style.fill[style.fill.length - 1]); + fillGradientStops.push(1); + if (style.fillGradientType === TEXT_GRADIENT.LINEAR_VERTICAL) { // start the gradient at the top center of the canvas, and end at the bottom middle of the canvas @@ -532,15 +555,22 @@ // we need to repeat the gradient so that each individual line of text has the same vertical gradient effect // ['#FF0000', '#00FF00', '#0000FF'] over 2 lines would create stops at 0.125, 0.25, 0.375, 0.625, 0.75, 0.875 - totalIterations = (style.fill.length + 1) * lines.length; + totalIterations = (fill.length + 1) * lines.length; currentIteration = 0; for (let i = 0; i < lines.length; i++) { currentIteration += 1; - for (let j = 0; j < style.fill.length; j++) + for (let j = 0; j < fill.length; j++) { - stop = (currentIteration / totalIterations); - gradient.addColorStop(stop, style.fill[j]); + if (fillGradientStops[j]) + { + stop = (fillGradientStops[j] / lines.length) + (i / lines.length); + } + else + { + stop = currentIteration / totalIterations; + } + gradient.addColorStop(stop, fill[j]); currentIteration++; } } @@ -552,13 +582,20 @@ // can just evenly space out the gradients in this case, as multiple lines makes no difference // to an even left to right gradient - totalIterations = style.fill.length + 1; + totalIterations = fill.length + 1; currentIteration = 1; - for (let i = 0; i < style.fill.length; i++) + for (let i = 0; i < fill.length; i++) { - stop = currentIteration / totalIterations; - gradient.addColorStop(stop, style.fill[i]); + if (fillGradientStops[i]) + { + stop = fillGradientStops[i]; + } + else + { + stop = currentIteration / totalIterations; + } + gradient.addColorStop(stop, fill[i]); currentIteration++; } } @@ -569,7 +606,7 @@ /** * Destroys this text object. * Note* Unlike a Sprite, a Text object will automatically destroy its baseTexture and texture as - * the majorety of the time the texture will not be shared with any other Sprites. + * the majority of the time the texture will not be shared with any other Sprites. * * @param {object|boolean} [options] - Options parameter. A boolean will act as if all options * have been set to that value diff --git a/src/core/text/TextStyle.js b/src/core/text/TextStyle.js index 3b25528..58e77e0 100644 --- a/src/core/text/TextStyle.js +++ b/src/core/text/TextStyle.js @@ -14,6 +14,7 @@ dropShadowDistance: 5, fill: 'black', fillGradientType: TEXT_GRADIENT.LINEAR_VERTICAL, + fillGradientStops: [], fontFamily: 'Arial', fontSize: 26, fontStyle: 'normal', @@ -55,8 +56,10 @@ * fillstyle that will be used on the text e.g 'red', '#00FF00'. Can be an array to create a gradient * eg ['#000000','#FFFFFF'] * {@link https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/fillStyle|MDN} - * @param {number} [style.fillGradientType=PIXI.TEXT_GRADIENT.LINEAR_VERTICAL] - If fills styles are - * supplied, this can change the type/direction of the gradient. See {@link PIXI.TEXT_GRADIENT} for possible values + * @param {number} [style.fillGradientType=PIXI.TEXT_GRADIENT.LINEAR_VERTICAL] - If fill is an array of colours + * to create a gradient, this can change the type/direction of the gradient. See {@link PIXI.TEXT_GRADIENT} + * @param {number[]} [style.fillGradientStops] - If fill is an array of colours to create a gradient, this array can set + * the stop points (numbers between 0 and 1) for the color, overriding the default behaviour of evenly spacing them. * @param {string|string[]} [style.fontFamily='Arial'] - The font family * @param {number|string} [style.fontSize=26] - The font size (as a number it converts to px, but as a string, * equivalents are '26px','20pt','160%' or '1.6em') @@ -232,6 +235,19 @@ } } + get fillGradientStops() + { + return this._fillGradientStops; + } + set fillGradientStops(fillGradientStops) + { + if (!areArraysEqual(this._fillGradientStops,fillGradientStops)) + { + this._fillGradientStops = fillGradientStops; + this.styleID++; + } + } + get fontFamily() { return this._fontFamily; @@ -475,3 +491,34 @@ return color; } } + +/** + * Utility function to convert hexadecimal colors to strings, and simply return the color if it's a string. + * This version can also convert array of colors + * + * @param {Array} array1 First array to compared + * @param {Array} array1 Second array to compare + * @return {boolean} Do the arrays contain the same values in the same order + */ +function areArraysEqual(array1, array2) +{ + if (!Array.isArray(array1) || !Array.isArray(array2)) + { + return false; + } + + if (array1.length !== array2.length) + { + return false; + } + + for (let i = 0; i < array1.length; ++i) + { + if (array1[i] !== array2[i]) + { + return false; + } + } + + return true; +}