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">
262 lines (258 loc) • 7.1 kB
JavaScript
'use strict';
var Container = require('../container/Container.js');
var TextStyle = require('../text/TextStyle.js');
"use strict";
class AbstractSplitText extends Container.Container {
constructor(config) {
const {
text,
style,
autoSplit,
lineAnchor,
wordAnchor,
charAnchor,
...options
} = config;
super(options);
this._dirty = false;
this._canReuseChars = false;
this.chars = [];
this.words = [];
this.lines = [];
this._originalText = text;
this._autoSplit = autoSplit;
this._lineAnchor = lineAnchor;
this._wordAnchor = wordAnchor;
this._charAnchor = charAnchor;
this.style = style;
}
/**
* Splits the text into lines, words, and characters.
* Call this manually when autoSplit is false.
* @example Manual Splitting
* ```ts
* const text = new SplitText({
* text: 'Manual Update',
* autoSplit: false
* });
*
* text.text = 'New Content';
* text.style = { fontSize: 32 };
* text.split(); // Apply changes
* ```
*/
split() {
const res = this.splitFn();
this.chars = res.chars;
this.words = res.words;
this.lines = res.lines;
this.addChild(...this.lines);
this.charAnchor = this._charAnchor;
this.wordAnchor = this._wordAnchor;
this.lineAnchor = this._lineAnchor;
this._dirty = false;
this._canReuseChars = true;
}
get text() {
return this._originalText;
}
/**
* Gets or sets the text content.
* Setting new text triggers splitting if autoSplit is true.
* > [!NOTE] Setting this frequently can have a performance impact, especially with large texts and canvas text.
* @example Dynamic Text Updates
* ```ts
* const text = new SplitText({
* text: 'Original',
* autoSplit: true
* });
*
* // Auto-splits on change
* text.text = 'Updated Content';
*
* // Manual update
* text.autoSplit = false;
* text.text = 'Manual Update';
* text.split();
* ```
*/
set text(value) {
this._originalText = value;
this.lines.forEach((line) => line.destroy({ children: true }));
this.lines.length = 0;
this.words.length = 0;
this.chars.length = 0;
this._canReuseChars = false;
this.onTextUpdate();
}
_setOrigin(value, elements, property) {
let originPoint;
if (typeof value === "number") {
originPoint = { x: value, y: value };
} else {
originPoint = { x: value.x, y: value.y };
}
elements.forEach((element) => {
const localBounds = element.getLocalBounds();
const originX = localBounds.minX + localBounds.width * originPoint.x;
const originY = localBounds.minY + localBounds.height * originPoint.y;
element.origin.set(originX, originY);
});
this[property] = value;
}
/**
* Gets or sets the transform anchor for line segments.
* The anchor point determines the center of rotation and scaling for each line.
* @example Setting Line Anchors
* ```ts
* // Center rotation/scaling
* text.lineAnchor = 0.5;
*
* // Rotate/scale from top-right corner
* text.lineAnchor = { x: 1, y: 0 };
*
* // Custom anchor point
* text.lineAnchor = {
* x: 0.2, // 20% from left
* y: 0.8 // 80% from top
* };
* ```
*/
get lineAnchor() {
return this._lineAnchor;
}
set lineAnchor(value) {
this._setOrigin(value, this.lines, "_lineAnchor");
}
/**
* Gets or sets the transform anchor for word segments.
* The anchor point determines the center of rotation and scaling for each word.
* @example
* ```ts
* // Center each word
* text.wordAnchor = 0.5;
*
* // Scale from bottom-left
* text.wordAnchor = { x: 0, y: 1 };
*
* // Rotate around custom point
* text.wordAnchor = {
* x: 0.75, // 75% from left
* y: 0.5 // Middle vertically
* };
* ```
*/
get wordAnchor() {
return this._wordAnchor;
}
set wordAnchor(value) {
this._setOrigin(value, this.words, "_wordAnchor");
}
/**
* Gets or sets the transform anchor for character segments.
* The anchor point determines the center of rotation and scaling for each character.
* @example Setting Character Anchors
* ```ts
* // Center each character
* text.charAnchor = 0.5;
*
* // Rotate from top-center
* text.charAnchor = { x: 0.5, y: 0 };
*
* // Scale from bottom-right
* text.charAnchor = { x: 1, y: 1 };
* ```
* @example Animation with Anchors
* ```ts
* // Rotate characters around their centers
* text.charAnchor = 0.5;
* text.chars.forEach((char, i) => {
* gsap.to(char, {
* rotation: Math.PI * 2,
* duration: 1,
* delay: i * 0.1,
* repeat: -1
* });
* });
* ```
*/
get charAnchor() {
return this._charAnchor;
}
set charAnchor(value) {
this._setOrigin(value, this.chars, "_charAnchor");
}
get style() {
return this._style;
}
/**
* The style configuration for the text.
* Can be a TextStyle instance or a configuration object.
* @example
* ```ts
* const text = new Text({
* text: 'Styled Text',
* style: {
* fontSize: 24,
* fill: 0xff1010, // Red color
* fontFamily: 'Arial',
* align: 'center', // Center alignment
* stroke: { color: '#4a1850', width: 5 }, // Purple stroke
* dropShadow: {
* color: '#000000', // Black shadow
* blur: 4, // Shadow blur
* distance: 6 // Shadow distance
* }
* }
* });
* // Update style dynamically
* text.style = {
* fontSize: 30, // Change font size
* fill: 0x00ff00, // Change color to green
* align: 'right', // Change alignment to right
* stroke: { color: '#000000', width: 2 }, // Add black stroke
* }
*/
set style(style) {
style || (style = {});
this._style = new TextStyle.TextStyle(style);
this.words.forEach((word) => word.destroy());
this.words.length = 0;
this.lines.forEach((line) => line.destroy());
this.lines.length = 0;
this._canReuseChars = true;
this.onTextUpdate();
}
onTextUpdate() {
this._dirty = true;
if (this._autoSplit) {
this.split();
}
}
/**
* Destroys the SplitText instance and all its resources.
* Cleans up all segment arrays, event listeners, and optionally the text style.
* @param options - Destroy configuration options
* @example
* ```ts
* // Clean up everything
* text.destroy({ children: true, texture: true, style: true });
*
* // Remove from parent but keep style
* text.destroy({ children: true, style: false });
* ```
*/
destroy(options) {
super.destroy(options);
this.chars = [];
this.words = [];
this.lines = [];
if (typeof options === "boolean" ? options : options?.style) {
this._style.destroy(options);
}
this._style = null;
this._originalText = "";
}
}
exports.AbstractSplitText = AbstractSplitText;
//# sourceMappingURL=AbstractSplitText.js.map