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 lines • 20.6 kB
Source Map (JSON)
{"version":3,"file":"AbstractSplitText.mjs","sources":["../../../src/scene/text-split/AbstractSplitText.ts"],"sourcesContent":["import { type PointData } from '../../maths/point/PointData';\nimport { Container, type ContainerOptions } from '../container/Container';\nimport { type DestroyOptions } from '../container/destroyTypes';\nimport { TextStyle, type TextStyleOptions } from '../text/TextStyle';\nimport { type SplitableTextObject, type TextSplitOutput } from './types';\n\n/**\n * Configuration options for text splitting.\n * @category text\n * @standard\n */\nexport interface AbstractSplitOptions\n{\n /** Text content to be split */\n text: string;\n\n /** Text styling - accepts TextStyle instance or style object */\n style: TextStyle | Partial<TextStyleOptions>;\n\n /**\n * Enables automatic splitting on text/style changes\n * @default true\n */\n autoSplit?: boolean;\n\n /**\n * Transform origin for line segments. Range: [0-1]\n * @example\n * ```ts\n * lineAnchor: 0.5 // Center horizontally and vertically\n * lineAnchor: { x: 0, y: 0.5 } // Left-center alignment\n *\n * ```\n * @default 0\n */\n lineAnchor?: number | PointData;\n\n /**\n * Transform origin for word segments. Range: [0-1]\n * @example\n * ```ts\n * wordAnchor: { x: 1, y: 0 } // Top-right alignment\n * wordAnchor: 0.5 // Center alignment\n * ```\n * @default 0\n */\n wordAnchor?: number | PointData;\n\n /**\n * Transform origin for character segments. Range: [0-1]\n * @example\n * ```ts\n * charAnchor: { x: 0.5, y: 1 } // Bottom-center alignment\n * charAnchor: 0.5 // Center alignment\n * ```\n * @default 0\n */\n charAnchor?: number | PointData;\n}\n\n/**\n * Configuration options for SplitText, combining container properties with text splitting settings.\n * @example Basic Usage\n * ```ts\n * const options: SplitTextOptions = {\n * text: 'Hello World',\n * style: { fontSize: 32, fill: 0xffffff },\n * // Transform origins\n * lineAnchor: 0.5, // Center each line\n * wordAnchor: { x: 0, y: 0.5 }, // Left-center each word\n * charAnchor: { x: 0.5, y: 1 }, // Bottom-center each char\n * };\n * ```\n * @example Advanced Configuration\n * ```ts\n * const options: SplitTextOptions = {\n * // Text content and style\n * text: 'Multi\\nLine Text',\n * style: new TextStyle({\n * fontSize: 24,\n * fill: 'white',\n * strokeThickness: 2,\n * }),\n *\n * // Container properties\n * x: 100,\n * y: 100,\n * alpha: 0.8,\n *\n * // Splitting settings\n * autoSplit: true,\n *\n * // Transform origins (normalized 0-1)\n * lineAnchor: { x: 1, y: 0 }, // Top-right\n * wordAnchor: 0.5, // Center\n * charAnchor: { x: 0, y: 1 }, // Bottom-left\n * };\n * ```\n *\n * Properties:\n * - Container options from {@link ContainerOptions}\n * - Text split options from {@link AbstractSplitOptions}\n * @see {@link AbstractSplitText} For the main implementation\n * @see {@link ContainerOptions} For base container properties\n * @see {@link AbstractSplitOptions} For text splitting options\n * @category text\n * @standard\n */\nexport interface AbstractSplitTextOptions extends ContainerOptions, AbstractSplitOptions {}\n\n/**\n * @experimental\n * A container that splits text into individually manipulatable segments (lines, words, and characters)\n * for advanced text effects and animations.\n * @example Basic Usage\n * ```ts\n * const text = new SplitText({\n * text: \"Hello World\",\n * style: { fontSize: 24 },\n * // Origin points for transformations (0-1 range)\n * lineAnchor: 0.5, // Center of each line\n * wordAnchor: { x: 0, y: 0.5 }, // Left-center of each word\n * charAnchor: { x: 0.5, y: 1 }, // Bottom-center of each character\n * autoSplit: true // Auto-update segments on text/style changes\n * });\n * ```\n *\n * Features:\n * - Hierarchical text splitting (lines → words → characters)\n * - Independent transformation origins for each segment level\n * - Automatic or manual segment updates\n * - Support for both canvas text and bitmap text\n * @example Animation Example\n * ```ts\n * // Character fade-in sequence\n * text.chars.forEach((char, i) => {\n * gsap.from(char, {\n * alpha: 0,\n * delay: i * 0.1\n * });\n * });\n *\n * // Word scale animation\n * text.words.forEach((word, i) => {\n * gsap.to(word.scale, {\n * x: 1.2, y: 1.2,\n * yoyo: true,\n * repeat: -1,\n * delay: i * 0.2\n * });\n * });\n *\n * // Line slide-in effect\n * text.lines.forEach((line, i) => {\n * gsap.from(line, {\n * x: -200,\n * delay: i * 0.3\n * });\n * });\n * ```\n *\n * Configuration Options:\n * - `text`: The string to render and segment\n * - `style`: TextStyle instance or configuration object\n * - `autoSplit`: Automatically update segments on changes (default: true)\n * - `lineAnchor`: Transform origin for lines (default: 0)\n * - `wordAnchor`: Transform origin for words (default: 0)\n * - `charAnchor`: Transform origin for characters (default: 0)\n *\n * > [!NOTE] Anchor points are normalized (0-1):\n * > - 0,0: Top-left\n * > - 0.5,0.5: Center\n * > - 1,1: Bottom-right\n *\n * > [!WARNING] Limitations\n * > - Character spacing may differ slightly from standard text due to browser\n * > kerning being lost when characters are separated\n * @category text\n * @standard\n */\nexport abstract class AbstractSplitText<T extends SplitableTextObject> extends Container\n{\n /**\n * Individual character segments of the text.\n * @example\n * ```ts\n * // Fade in characters sequentially\n * text.chars.forEach((char, i) => {\n * char.alpha = 0;\n * gsap.to(char, {\n * alpha: 1,\n * delay: i * 0.1\n * });\n * });\n * ```\n */\n public chars: T[];\n\n /**\n * Word segments of the text, each containing one or more characters.\n * @example\n * ```ts\n * // Scale words on hover\n * text.words.forEach(word => {\n * word.interactive = true;\n * word.on('pointerover', () => {\n * gsap.to(word.scale, { x: 1.2, y: 1.2 });\n * });\n * word.on('pointerout', () => {\n * gsap.to(word.scale, { x: 1, y: 1 });\n * });\n * });\n * ```\n */\n public words: Container[];\n\n /**\n * Line segments of the text, each containing one or more words.\n * @example\n * ```ts\n * // Stagger line entrance animations\n * text.lines.forEach((line, i) => {\n * line.x = -200;\n * gsap.to(line, {\n * x: 0,\n * duration: 0.5,\n * delay: i * 0.2,\n * ease: 'back.out'\n * });\n * });\n * ```\n */\n public lines: Container[];\n\n protected _originalText: string;\n protected _lineAnchor: number | PointData;\n protected _wordAnchor: number | PointData;\n protected _charAnchor: number | PointData;\n protected _autoSplit: boolean;\n protected _style: TextStyle;\n\n protected _dirty: boolean = false;\n protected _canReuseChars: boolean = false;\n\n constructor(config: AbstractSplitTextOptions)\n {\n const {\n text,\n style,\n autoSplit,\n lineAnchor,\n wordAnchor,\n charAnchor,\n ...options\n } = config;\n\n super(options);\n this.chars = [];\n this.words = [];\n this.lines = [];\n\n this._originalText = text;\n this._autoSplit = autoSplit;\n this._lineAnchor = lineAnchor;\n this._wordAnchor = wordAnchor;\n this._charAnchor = charAnchor;\n\n // setting the style will segment the text if autoSplit is true\n this.style = style;\n }\n\n protected abstract splitFn(): TextSplitOutput<T>;\n\n /**\n * Splits the text into lines, words, and characters.\n * Call this manually when autoSplit is false.\n * @example Manual Splitting\n * ```ts\n * const text = new SplitText({\n * text: 'Manual Update',\n * autoSplit: false\n * });\n *\n * text.text = 'New Content';\n * text.style = { fontSize: 32 };\n * text.split(); // Apply changes\n * ```\n */\n public split(): void\n {\n const res: TextSplitOutput<T> = this.splitFn();\n\n this.chars = res.chars;\n this.words = res.words;\n this.lines = res.lines;\n\n this.addChild(...this.lines);\n\n // force origin to be set\n this.charAnchor = this._charAnchor;\n this.wordAnchor = this._wordAnchor;\n this.lineAnchor = this._lineAnchor;\n\n this._dirty = false;\n this._canReuseChars = true;\n }\n\n get text(): string\n {\n return this._originalText;\n }\n /**\n * Gets or sets the text content.\n * Setting new text triggers splitting if autoSplit is true.\n * > [!NOTE] Setting this frequently can have a performance impact, especially with large texts and canvas text.\n * @example Dynamic Text Updates\n * ```ts\n * const text = new SplitText({\n * text: 'Original',\n * autoSplit: true\n * });\n *\n * // Auto-splits on change\n * text.text = 'Updated Content';\n *\n * // Manual update\n * text.autoSplit = false;\n * text.text = 'Manual Update';\n * text.split();\n * ```\n */\n set text(value: string)\n {\n this._originalText = value;\n this.lines.forEach((line) => line.destroy({ children: true }));\n this.lines.length = 0;\n this.words.length = 0;\n this.chars.length = 0;\n this._canReuseChars = false;\n // You can't reuse chars if the text changes\n this.onTextUpdate();\n }\n\n private _setOrigin(\n value: number | PointData,\n elements: Array<Container | T>,\n property: '_lineAnchor' | '_wordAnchor' | '_charAnchor',\n ): void\n {\n let originPoint: PointData;\n\n if (typeof value === 'number')\n {\n originPoint = { x: value, y: value };\n }\n else\n {\n originPoint = { x: value.x, y: value.y };\n }\n\n elements.forEach((element) =>\n {\n const localBounds = element.getLocalBounds();\n\n // Calculate origin position relative to the bounds\n const originX = localBounds.minX + (localBounds.width * originPoint.x);\n const originY = localBounds.minY + (localBounds.height * originPoint.y);\n\n element.origin.set(originX, originY);\n });\n\n this[property] = value;\n }\n\n /**\n * Gets or sets the transform anchor for line segments.\n * The anchor point determines the center of rotation and scaling for each line.\n * @example Setting Line Anchors\n * ```ts\n * // Center rotation/scaling\n * text.lineAnchor = 0.5;\n *\n * // Rotate/scale from top-right corner\n * text.lineAnchor = { x: 1, y: 0 };\n *\n * // Custom anchor point\n * text.lineAnchor = {\n * x: 0.2, // 20% from left\n * y: 0.8 // 80% from top\n * };\n * ```\n */\n get lineAnchor(): number | PointData\n {\n return this._lineAnchor;\n }\n set lineAnchor(value: number | PointData)\n {\n this._setOrigin(value, this.lines, '_lineAnchor');\n }\n\n /**\n * Gets or sets the transform anchor for word segments.\n * The anchor point determines the center of rotation and scaling for each word.\n * @example\n * ```ts\n * // Center each word\n * text.wordAnchor = 0.5;\n *\n * // Scale from bottom-left\n * text.wordAnchor = { x: 0, y: 1 };\n *\n * // Rotate around custom point\n * text.wordAnchor = {\n * x: 0.75, // 75% from left\n * y: 0.5 // Middle vertically\n * };\n * ```\n */\n get wordAnchor(): number | PointData\n {\n return this._wordAnchor;\n }\n set wordAnchor(value: number | PointData)\n {\n this._setOrigin(value, this.words, '_wordAnchor');\n }\n\n /**\n * Gets or sets the transform anchor for character segments.\n * The anchor point determines the center of rotation and scaling for each character.\n * @example Setting Character Anchors\n * ```ts\n * // Center each character\n * text.charAnchor = 0.5;\n *\n * // Rotate from top-center\n * text.charAnchor = { x: 0.5, y: 0 };\n *\n * // Scale from bottom-right\n * text.charAnchor = { x: 1, y: 1 };\n * ```\n * @example Animation with Anchors\n * ```ts\n * // Rotate characters around their centers\n * text.charAnchor = 0.5;\n * text.chars.forEach((char, i) => {\n * gsap.to(char, {\n * rotation: Math.PI * 2,\n * duration: 1,\n * delay: i * 0.1,\n * repeat: -1\n * });\n * });\n * ```\n */\n get charAnchor(): number | PointData\n {\n return this._charAnchor;\n }\n set charAnchor(value: number | PointData)\n {\n this._setOrigin(value, this.chars, '_charAnchor');\n }\n\n get style(): TextStyle\n {\n return this._style;\n }\n\n /**\n * The style configuration for the text.\n * Can be a TextStyle instance or a configuration object.\n * @example\n * ```ts\n * const text = new Text({\n * text: 'Styled Text',\n * style: {\n * fontSize: 24,\n * fill: 0xff1010, // Red color\n * fontFamily: 'Arial',\n * align: 'center', // Center alignment\n * stroke: { color: '#4a1850', width: 5 }, // Purple stroke\n * dropShadow: {\n * color: '#000000', // Black shadow\n * blur: 4, // Shadow blur\n * distance: 6 // Shadow distance\n * }\n * }\n * });\n * // Update style dynamically\n * text.style = {\n * fontSize: 30, // Change font size\n * fill: 0x00ff00, // Change color to green\n * align: 'right', // Change alignment to right\n * stroke: { color: '#000000', width: 2 }, // Add black stroke\n * }\n */\n set style(style: TextStyle | Partial<TextStyle> | TextStyleOptions)\n {\n style ||= {};\n\n this._style = new TextStyle(style);\n\n // tidy up word/line containers, characters can be reused\n this.words.forEach((word) => word.destroy());\n this.words.length = 0;\n\n this.lines.forEach((line) => line.destroy());\n this.lines.length = 0;\n\n this._canReuseChars = true;\n\n this.onTextUpdate();\n }\n\n protected onTextUpdate(): void\n {\n this._dirty = true;\n\n if (this._autoSplit)\n {\n this.split();\n }\n }\n\n /**\n * Destroys the SplitText instance and all its resources.\n * Cleans up all segment arrays, event listeners, and optionally the text style.\n * @param options - Destroy configuration options\n * @example\n * ```ts\n * // Clean up everything\n * text.destroy({ children: true, texture: true, style: true });\n *\n * // Remove from parent but keep style\n * text.destroy({ children: true, style: false });\n * ```\n */\n public destroy(options?: DestroyOptions): void\n {\n super.destroy(options);\n this.chars = [];\n this.words = [];\n this.lines = [];\n if (typeof options === 'boolean' ? options : options?.style)\n {\n this._style.destroy(options);\n }\n\n this._style = null;\n this._originalText = '';\n }\n}\n"],"names":[],"mappings":"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"}