From bd3c92b04595fbbe19fc77c28ff038611af789bb Mon Sep 17 00:00:00 2001 From: Dmytro Soldatov Date: Tue, 26 Mar 2024 22:35:51 +0200 Subject: [PATCH] fix issues --- src/Layout.ts | 6 +- src/controllers/ContentController.ts | 22 ++-- src/controllers/SizeController.ts | 13 +-- src/controllers/StyleController.ts | 6 +- src/stories/autoSize/BySetSize.stories.ts | 20 +++- src/stories/basic/ContentAdd.stories.ts | 12 +- src/stories/complex/NineSlicePlane.stories.ts | 30 +++-- src/utils/helpers.ts | 110 +++--------------- src/utils/text.ts | 16 +++ src/utils/types.ts | 10 +- 10 files changed, 100 insertions(+), 145 deletions(-) create mode 100644 src/utils/text.ts diff --git a/src/Layout.ts b/src/Layout.ts index 3c32d67..3af0cf4 100644 --- a/src/Layout.ts +++ b/src/Layout.ts @@ -4,7 +4,7 @@ import { AlignController } from "./controllers/AlignController"; import { StyleController } from "./controllers/StyleController"; import { SizeController } from "./controllers/SizeController"; import { ContentController } from "./controllers/ContentController"; -import type { TextStyle } from "pixi.js"; +import { PixiTextStyle } from "./utils/text"; /** * Layout controller class for any PixiJS Container based instance. @@ -216,7 +216,7 @@ export class LayoutSystem { } /** Layout text styles. */ - get textStyle(): Partial { + get textStyle(): Partial { return this._style.textStyle; } @@ -366,7 +366,7 @@ export class Layout extends Container { } /** Layout text styles. */ - get textStyle(): Partial { + get textStyle(): Partial { return this.layout.textStyle; } diff --git a/src/controllers/ContentController.ts b/src/controllers/ContentController.ts index 721cb91..5f29b3a 100644 --- a/src/controllers/ContentController.ts +++ b/src/controllers/ContentController.ts @@ -7,10 +7,9 @@ import { LayoutOptions, LayoutStyles, } from "../utils/types"; -import { Container, Graphics } from "pixi.js"; -import { Text, TextStyle } from "pixi.js"; -import { Sprite } from "pixi.js"; +import { Container, Graphics, Text, Sprite } from "pixi.js"; import { stylesToPixiTextStyles } from "../utils/helpers"; +import { PixiTextStyle } from "../utils/text"; /** Controls all {@link LayoutSystem} children sizing. */ export class ContentController { @@ -73,7 +72,10 @@ export class ContentController { ); break; case "string": - const text = new Text(content as string, this.layout.textStyle); + const text = new Text({ + text: content, + style: this.layout.textStyle, + }); this.addContentElement(`text-${customID}`, text); break; @@ -81,7 +83,7 @@ export class ContentController { const textInstance = content as Text; for (const key in this.layout.textStyle) { - const styleKey = key as keyof TextStyle; + const styleKey = key as keyof PixiTextStyle; (textInstance.style as any)[styleKey] = this.layout.textStyle[styleKey]; @@ -138,10 +140,10 @@ export class ContentController { }; } - const text = new Text( - contentElement as string, - defaultStyles - ); + const text = new Text({ + text: contentElement, + style: defaultStyles, + }); this.addContentElement(idKey, text); break; @@ -335,7 +337,7 @@ export class ContentController { } } - protected getChild(childInstance: DisplayObject): string | undefined { + protected getChild(childInstance: Container): string | undefined { for (const [key, value] of this.children.entries()) { if (value === childInstance) { return key; diff --git a/src/controllers/SizeController.ts b/src/controllers/SizeController.ts index e43bad6..11f5d51 100644 --- a/src/controllers/SizeController.ts +++ b/src/controllers/SizeController.ts @@ -1,5 +1,5 @@ /* eslint-disable no-case-declarations */ -import { getColor, getNumber, isItJustAText } from "../utils/helpers"; +import { getNumber, isItJustAText } from "../utils/helpers"; import { LayoutSystem } from "../Layout"; import { Text } from "pixi.js"; import { Container } from "pixi.js"; @@ -324,7 +324,7 @@ export class SizeController { break; } } else { - const color = background !== "transparent" && getColor(background); + const color = background !== "transparent" && background; const { borderRadius } = this.layout.style; const { width, height } = this; @@ -351,8 +351,8 @@ export class SizeController { if (this.bg instanceof Graphics) { this.bg .clear() - .beginFill(color.hex, color.opacity) - .drawRoundedRect(x, y, width, height, borderRadius); + .roundRect(x, y, width, height, borderRadius) + .fill(color); } } else if (this.bg) { this.layout.container.removeChild(this.bg); @@ -387,9 +387,8 @@ export class SizeController { this.overflowMask .clear() - .beginFill(0xffffff) - .drawRoundedRect(x, y, width, height, borderRadius) - .endFill(); + .roundRect(x, y, width, height, borderRadius) + .fill(0xffffff); this.layout.container.mask = this.overflowMask; } else { diff --git a/src/controllers/StyleController.ts b/src/controllers/StyleController.ts index 52b40f2..f82d414 100644 --- a/src/controllers/StyleController.ts +++ b/src/controllers/StyleController.ts @@ -1,9 +1,9 @@ import { TilingSprite, NineSliceSprite } from "pixi.js"; import type { ConditionalStyles, GradeToOne, Styles } from "../utils/types"; -import { TextStyle } from "pixi.js"; import { stylesToPixiTextStyles } from "../utils/helpers"; import { BACKGROUND_SIZE, OVERFLOW, VERTICAL_ALIGN } from "../utils/constants"; import { LayoutSystem } from "../Layout"; +import { PixiTextStyle } from "../utils/text"; /** Style controller manages {@link LayoutSystem} styles. */ export class StyleController { @@ -12,7 +12,7 @@ export class StyleController { protected styles: Styles = {}; /** Holds all text related styles. This is to be nested by children */ - protected _textStyle: Partial = {}; // this is to be nested by children + protected _textStyle: Partial = {}; // this is to be nested by children /** Stores default styles. */ protected defaultStyles: Styles; @@ -175,7 +175,7 @@ export class StyleController { } /** Returns all pixi text related styles of the Layout */ - get textStyle(): Partial { + get textStyle(): Partial { return this._textStyle; } diff --git a/src/stories/autoSize/BySetSize.stories.ts b/src/stories/autoSize/BySetSize.stories.ts index d00b7a0..4c2846b 100644 --- a/src/stories/autoSize/BySetSize.stories.ts +++ b/src/stories/autoSize/BySetSize.stories.ts @@ -13,19 +13,21 @@ const TEXTS = [ ]; const args = { - type: ["NineSliceSprite", "Sprite"], + type: ["Sprite", "NineSliceSprite"], text: TEXTS.join("\n\n"), - width: 350, + width: 650, height: 350, padding: 35, textAlign: ALIGN, wordWrap: true, - backgroundSize: BACKGROUND_SIZE, + backgroundSize: [ + BACKGROUND_SIZE[3], + ...BACKGROUND_SIZE.filter((_, i) => i > 3), + ], }; const assets = { background: "Window/SmallSubstrate.png", - NineSliceSprite: "Progress/ValueBG.png", }; class LayoutStory { @@ -54,9 +56,15 @@ class LayoutStory { let background: Sprite | NineSliceSprite; if (type === "NineSliceSprite") { - const substrateTexture = Texture.from(assets.NineSliceSprite); + const substrateTexture = Texture.from(assets.background); - background = new NineSliceSprite(substrateTexture, 53, 50, 53, 56); + background = new NineSliceSprite({ + texture: substrateTexture, + leftWidth: 53, + topHeight: 50, + rightWidth: 53, + bottomHeight: 56, + }); } else { background = Sprite.from(assets.background); } diff --git a/src/stories/basic/ContentAdd.stories.ts b/src/stories/basic/ContentAdd.stories.ts index 6ee603e..45246a9 100644 --- a/src/stories/basic/ContentAdd.stories.ts +++ b/src/stories/basic/ContentAdd.stories.ts @@ -123,8 +123,8 @@ class LayoutStory { }), stringID1: "Text 1", // string container1: new Graphics() // Pixi.Container - .beginFill(0xff0000) - .drawCircle(20, 20, 20), + .fill(0xff0000) + .circle(20, 20, 20), textID: new Text("Text 2"), // PIXI.Text layoutConfig: { content: "Layout Config", @@ -145,10 +145,10 @@ class LayoutStory { // this has to be layout config, can not just be string id: "string4", content: new Graphics() // Pixi.Container - .beginFill(0x007eff) - .drawRoundedRect(0, 0, 100, 100, 20) - .beginFill(0xfff200) - .drawCircle(20, 20, 10), + .fill(0x007eff) + .roundRect(0, 0, 100, 100, 20) + .fill(0xfff200) + .circle(20, 20, 10), }, ], }, diff --git a/src/stories/complex/NineSlicePlane.stories.ts b/src/stories/complex/NineSlicePlane.stories.ts index eaeeb89..f703c47 100644 --- a/src/stories/complex/NineSlicePlane.stories.ts +++ b/src/stories/complex/NineSlicePlane.stories.ts @@ -30,19 +30,31 @@ class LayoutStory { createLayout(props: typeof args) { const titleTexture = Texture.from(testAssets.ribbon); - const titleBG = new NineSliceSprite(titleTexture, 315, 64, 112, 73); + const titleBG = new NineSliceSprite({ + texture: titleTexture, + leftWidth: 315, + topHeight: 64, + rightWidth: 112, + bottomHeight: 73, + }); const windowTexture = Texture.from(testAssets.window); - const windowBG = new NineSliceSprite(windowTexture, 315, 64, 112, 73); + const windowBG = new NineSliceSprite({ + texture: windowTexture, + leftWidth: 315, + topHeight: 64, + rightWidth: 112, + bottomHeight: 73, + }); const substrateTexture = Texture.from(testAssets.substrate); - const substrateBG = new NineSliceSprite( - substrateTexture, - 400, - 64, - 400, - 73 - ); + const substrateBG = new NineSliceSprite({ + texture: substrateTexture, + leftWidth: 400, + topHeight: 64, + rightWidth: 400, + bottomHeight: 73, + }); // Component usage this.layout = new Layout({ diff --git a/src/utils/helpers.ts b/src/utils/helpers.ts index 2ec280a..89d28e4 100644 --- a/src/utils/helpers.ts +++ b/src/utils/helpers.ts @@ -1,7 +1,7 @@ -import { CSS_COLOR_NAMES } from "./constants"; -import { Color, CSSColor, FlexColor, FlexNumber, Styles } from "./types"; -import { utils, TextStyle, Text } from "pixi.js"; +import { FlexNumber, Styles } from "./types"; +import { Text } from "pixi.js"; import { LayoutSystem } from "../Layout"; +import { PixiTextStyle } from "./text"; export function rgba2Hex([r, g, b]: number[]): number { return parseInt(`0x${getHex(r)}${getHex(g)}${getHex(b)}`, 16); @@ -13,90 +13,10 @@ export function getHex(n: number) { return hex.length === 1 ? `0${hex}` : hex; } -export function hsl2Hex(h: number, s: number, l: number): number { - l /= 100; - - const a = (s * Math.min(l, 1 - l)) / 100; - const f = (n: number) => { - const k = (n + h / 30) % 12; - const color = l - a * Math.max(Math.min(k - 3, 9 - k, 1), -1); - - return Math.round(255 * color) - .toString(16) - .padStart(2, "0"); // convert to Hex and prefix "0" if needed - }; - - return utils.string2hex(`#${f(0)}${f(8)}${f(4)}`); -} - export function isDefined(value: any): boolean { return value !== undefined && value !== null; } -export function getColor(color: FlexColor): Color { - if (color === "transparent") { - return undefined; - } - - if (color === undefined) { - return undefined; - } - - switch (typeof color) { - case "string": - if (color.startsWith("#") || color.startsWith("0x")) { - return { - hex: utils.string2hex(color), - opacity: 1, - }; - } else if (color.startsWith("rgba(")) { - const colorData = color.slice(5, -1).split(","); - const rgbData = colorData.map((v) => parseInt(v, 10)); - - return { - hex: rgba2Hex(rgbData), - opacity: parseFloat(colorData[3]), - }; - } else if (color.startsWith("rgb(")) { - const colorData = color.slice(5, -1).split(","); - const rgbData = colorData.map((v) => parseInt(v, 10)); - - return { - hex: utils.rgb2hex(rgbData), - opacity: 1, - }; - } else if (color.startsWith("hsla(")) { - const colorData = color.slice(5, -1).split(","); - const [r, g, b] = colorData.map((v) => parseInt(v, 10)); - - return { - hex: hsl2Hex(r, g, b), - opacity: parseFloat(colorData[3]), - }; - } else if ( - Object.keys(CSS_COLOR_NAMES).includes(color as CSSColor) - ) { - return { - hex: CSS_COLOR_NAMES[color as CSSColor], - opacity: 1, - }; - } - throw new Error(`Unknown color format: ${color}`); - - case "number": - return { - hex: color, - opacity: 1, - }; - - default: - return { - hex: parseInt(color, 16), - opacity: 1, - }; - } -} - export function getNumber(value: FlexNumber, maxPercentValue?: number): number { if (value === undefined) { return undefined; @@ -123,19 +43,27 @@ export function getNumber(value: FlexNumber, maxPercentValue?: number): number { return 0; } -export function stylesToPixiTextStyles(styles: Styles): Partial { - const resultStyles: Partial = { +export function stylesToPixiTextStyles(styles: Styles): PixiTextStyle { + const resultStyles: PixiTextStyle = { align: styles?.textAlign, breakWords: styles?.breakWords, dropShadow: styles?.dropShadow, + fill: styles?.fill ?? styles?.color, + dropShadowAlpha: styles?.dropShadowAlpha, dropShadowAngle: styles?.dropShadowAngle, dropShadowBlur: styles?.dropShadowBlur, dropShadowColor: styles?.dropShadowColor, dropShadowDistance: styles?.dropShadowDistance, - fill: styles?.fill ?? getColor(styles?.color)?.hex, fillGradientType: styles?.fillGradientType, fillGradientStops: styles?.fillGradientStops, + lineJoin: styles?.lineJoin, + miterLimit: styles?.miterLimit, + strokeThickness: styles?.strokeThickness, + textBaseline: styles?.textBaseline, + trim: styles?.trim, + leading: styles?.leading, + fontFamily: styles?.fontFamily, fontSize: styles?.fontSize, fontStyle: styles?.fontStyle, @@ -143,22 +71,16 @@ export function stylesToPixiTextStyles(styles: Styles): Partial { fontWeight: styles?.fontWeight, letterSpacing: styles?.letterSpacing, lineHeight: styles?.lineHeight, - lineJoin: styles?.lineJoin, - miterLimit: styles?.miterLimit, // padding: styles?.padding ?? 0, stroke: styles?.stroke, - strokeThickness: styles?.strokeThickness, - textBaseline: styles?.textBaseline, - trim: styles?.trim, whiteSpace: styles?.whiteSpace, wordWrap: styles?.wordWrap, wordWrapWidth: styles?.wordWrapWidth ?? 100, - leading: styles?.leading, }; for (const key in resultStyles) { - if (resultStyles[key as keyof Partial] === undefined) { - delete resultStyles[key as keyof Partial]; + if (resultStyles[key as keyof Partial] === undefined) { + delete resultStyles[key as keyof Partial]; } } diff --git a/src/utils/text.ts b/src/utils/text.ts new file mode 100644 index 0000000..9d031d3 --- /dev/null +++ b/src/utils/text.ts @@ -0,0 +1,16 @@ +import { AbstractText, AnyTextStyle, AnyTextStyleOptions, Text } from 'pixi.js'; + +export type PixiText = AbstractText; +export type AnyText = string | number | PixiText; +export type PixiTextClass = new ({ text, style }: { text: string; style?: PixiTextStyle; [x: string]: any }) => PixiText; +export type PixiTextStyle = AnyTextStyle | Partial; + +export function getTextView(text: AnyText): PixiText +{ + if (typeof text === 'string' || typeof text === 'number') + { + return new Text({ text: String(text) }); + } + + return text; +} diff --git a/src/utils/types.ts b/src/utils/types.ts index 16cbfa9..321547e 100644 --- a/src/utils/types.ts +++ b/src/utils/types.ts @@ -1,9 +1,4 @@ -import type { - TilingSprite, - NineSliceSprite, - TextStyle, - TextStyleAlign, -} from "pixi.js"; +import type { TilingSprite, NineSliceSprite, TextStyleAlign } from "pixi.js"; import type { Container } from "pixi.js"; import { CSS_COLOR_NAMES, @@ -14,6 +9,7 @@ import { BACKGROUND_SIZE, } from "./constants"; import type { Layout } from "../Layout"; +import { PixiTextStyle } from "./text"; export type GradeToOne = | 0 @@ -61,7 +57,7 @@ export type ConditionalStyles = { export type BackgroundSize = (typeof BACKGROUND_SIZE)[number]; -export type Styles = Partial & { +export type Styles = Partial & { background?: | FlexColor | Container