Text
TextComponent is for free-positioned text on a render layer — a debug
HUD overlay, a diegetic floor label, a one-off world-space string that
should zoom and rotate with the camera. It’s Transform-synced like a
sprite, serializable, and takes a style object that mirrors CSS font
properties.
import { TextComponent } from "@yagejs/renderer";
entity.add(new Transform());entity.add( new TextComponent({ text: "DEBUG", layer: "debug", anchor: { x: 0.5, y: 0 }, style: { fontFamily: "ui-monospace, monospace", fontSize: 14, fill: 0xf8fafc, fontWeight: "bold", }, }),);Update at runtime with setText() / setStyle(), or tweak tint and
alpha directly.
When to reach for UI instead
Section titled “When to reach for UI instead”For most “text on screen” cases — HUD cards, score readouts with a
backdrop, dialog boxes, nameplates above an enemy, floating damage numbers
that should stay axis-aligned at any zoom — UIPanel + UIText from
@yagejs/ui is the right answer. You get flexbox layout (padding, gap,
alignment), a styled background fill, and child stacking, all of which
TextComponent deliberately doesn’t try to provide.
Specifically:
- Text widget with layout / padding / backdrop →
UIPanel+UIText. - Entity-tracked text that stays constant-size at any zoom (nameplates,
damage numbers, interaction prompts) →
ScreenFollow+UIPanel({ positioning: "transform" }). - Free string with no layout, that should follow camera transforms
(diegetic floor label, debug overlay, world-pinned billboard text) →
TextComponent.
Wrapper
Section titled “Wrapper”Thin wrapper: the style option forwards as-is to pixi’s
TextStyleOptions — full set of CSS-style font properties available
(fontFamily, fontSize, fontWeight, fontStyle, fill,
letterSpacing, lineHeight, dropShadow, etc.). .text is the
underlying pixi Text instance (or BitmapText when bitmap is set).
See the pixi Text guide
and TextStyle reference
for every available option.
Pixel-art text (bitmap)
Section titled “Pixel-art text (bitmap)”Canvas-rasterised Text is bilinear-sampled by the GPU, so it goes
blurry the moment it’s drawn at a non-integer scale — a zoomed
pixel-art camera, a 4× upscale — on a non-Retina display. BitmapText
draws pre-baked glyph quads instead, so it stays crisp. Set the bitmap
option (works on TextComponent and UIText alike):
// Zero-config: bake a dynamic bitmap font from this text's own style.new TextComponent({ text: "SCORE", bitmap: true, style: { fontFamily: "monospace", fontSize: 12 },});
// Render with an installed / loaded bitmap font by name. `size`// overrides the glyph size.new TextComponent({ text: "READY", bitmap: { font: "PressStart", size: 16 } });To bake a bitmap atlas from a .ttf at runtime, use
installBitmapFont — it loads the font and returns a name you hand
straight to bitmap: { font }:
import { installBitmapFont, TextComponent } from "@yagejs/renderer";
const font = await installBitmapFont("fonts/PressStart2P.ttf", { name: "PressStart", size: 16, // glyph bake size (default 32) resolution: 2, // keeps glyphs crisp when upscaled (default 2)});entity.add(new TextComponent({ text: "READY", bitmap: { font } }));For a pre-built BMFont (.fnt/.xml + atlas), preload the
bitmapFont("fonts/x.fnt") handle through a scene’s preload and pass
the fontFamily declared in the descriptor as bitmap: { font }.
Bitmap text honours the same Yoga word-wrap / truncate behaviour as
canvas text inside a UIPanel.
The Pixi v8 resolution gotcha
Section titled “The Pixi v8 resolution gotcha”In Pixi v8, resolution is a Text constructor option, not a
TextStyle property. Setting TextStyle.defaultTextStyle.resolution
does nothing — text stays rasterised at resolution 1 and blurs when
scaled. There’s no global toggle; pass resolution per text:
new TextComponent({ text: "HUD", resolution: window.devicePixelRatio });resolution is ignored when bitmap is set — a bitmap font’s
resolution is fixed when its atlas is baked
(installBitmapFont({ resolution })). For genuinely pixel-perfect
text at any zoom, prefer bitmap over chasing canvas resolution.