skills/pixijs-scene-text/references/bitmap-text.md
Text rendered from a pre-generated texture atlas of glyphs. Updating the text string only repositions quads; no canvas re-render, no GPU upload per change. Use BitmapText for scores, timers, gameplay labels, and any text whose content changes frequently. Trade-off: limited styling, fixed glyph set, pixel-perfect only at the font's native size (unless you use MSDF).
const score = new BitmapText({
text: "Score: 0",
style: {
fontFamily: "Arial",
fontSize: 32,
fill: 0xffffff,
},
});
app.stage.addChild(score);
app.ticker.add(() => {
score.text = `Score: ${Math.floor(performance.now() / 100)}`;
});
When you pass a system font family without calling BitmapFont.install, the text-bitmap system generates a dynamic bitmap font on first use.
const minimal = new BitmapText({ text: "Score: 0" });
const styled = new BitmapText({
text: "Hello",
style: { fontFamily: "GameFont", fontSize: 48, fill: 0xff0000 },
anchor: 0.5,
roundPixels: true,
});
BitmapText's constructor accepts the base TextOptions directly (no additional bitmap-specific fields). Fields match references/text.md with two caveats: style is still TextStyle \| TextStyleOptions (the same class Text uses, but many style fields are ignored by the bitmap pipeline), and resolution is managed by the underlying BitmapFont at install time rather than per-instance.
| Option | Type | Default | Description |
|---|---|---|---|
text | TextString | '' | Text content. Same as Text. |
style | TextStyle | TextStyleOptions | new TextStyle() with fill = 0xffffff | Shared TextStyle type; fields like fontFamily, fontSize, fill, stroke, align, wordWrap, wordWrapWidth, and lineHeight are respected. Gradients as fill and filters are not. See the TextStyle reference in references/text.md. |
anchor | PointData | number | 0 | Same as Text. |
resolution | number | null | null | Accepted but ignored at runtime — set resolution on the BitmapFont via BitmapFont.install({ resolution }) instead. Passing a non-null value logs a warning. |
roundPixels | boolean | false | Same as Text. |
All Container options (position, scale, tint, label, filters, zIndex, etc.) are also valid here — see skills/pixijs-scene-core-concepts/references/constructor-options.md.
BitmapTextdoes NOT accepttextureStyleorautoGenerateMipmaps; those are specific to canvasTextandHTMLText. The atlas texture style is controlled when installing the font viaBitmapFont.install({ textureStyle }).
const dynamic = new BitmapText({
text: "Hello",
style: { fontFamily: "Arial", fontSize: 32, fill: 0xff1010 },
});
The first BitmapText with a given fontFamily + fontSize generates an atlas lazily. Subsequent BitmapText instances reuse it. The system also scales an existing close-match size rather than re-generating.
import { BitmapFont } from "pixi.js";
BitmapFont.install({
name: "GameFont",
style: {
fontFamily: "Arial",
fontSize: 48,
fill: 0xffffff,
stroke: { color: "#000000", width: 2 },
},
});
const title = new BitmapText({
text: "Level 1",
style: { fontFamily: "GameFont", fontSize: 48, fill: 0x00ff00 },
});
BitmapFont.install pre-generates an atlas so the first BitmapText render has no setup cost. Useful for known fixed styles in a game.
| Option | Purpose |
|---|---|
chars | Character set to pre-render. Accepts a string, nested ranges, or a preset: BitmapFontManager.ALPHA, BitmapFontManager.NUMERIC, BitmapFontManager.ALPHANUMERIC, BitmapFontManager.ASCII. Essential for non-ASCII, CJK, or restricted charsets. |
resolution | Texture atlas resolution. Default 1. Use window.devicePixelRatio for HiDPI displays. |
padding | Glyph padding inside the atlas. Default 4. Raise to avoid bleeding at large scales. |
skipKerning | Skip kerning metadata to save memory and install time. Default false. |
textureStyle | TextureStyle/TextureStyleOptions override for the generated atlas (for example { scaleMode: 'nearest' } for pixel fonts). |
dynamicFill | Allow runtime tinting via BitmapText.tint. Requires the font style.fill to be white, no stroke, no drop shadow, or a drop shadow with color 0x000000 (black). The idiomatic way to color bitmap text without generating a new atlas per color. |
import { BitmapFont, BitmapFontManager } from "pixi.js";
BitmapFont.install({
name: "UIFont",
chars: BitmapFontManager.ALPHANUMERIC,
resolution: window.devicePixelRatio,
padding: 8,
skipKerning: true,
textureStyle: { scaleMode: "nearest" },
dynamicFill: true,
style: { fontFamily: "Arial", fontSize: 32, fill: 0xffffff },
});
const hp = new BitmapText({
text: "100",
style: { fontFamily: "UIFont", fill: "red" },
});
const mp = new BitmapText({
text: "50",
style: { fontFamily: "UIFont", fill: "blue" },
});
import "pixi.js/text-bitmap";
import { Assets, BitmapText } from "pixi.js";
await Assets.load("fonts/arcade.fnt");
const arcade = new BitmapText({
text: "HIGH SCORE",
style: { fontFamily: "arcade", fontSize: 36 },
});
Load .fnt or .xml files (AngelCode BMFont format) via Assets. Generate them from a .ttf / .otf with AssetPack. The side-effect import 'pixi.js/text-bitmap' registers the loader; required for custom builds that set skipExtensionImports: true.
Multi-channel Signed Distance Field (MSDF) fonts stay sharp at any size. Generate them with AssetPack (Pixi's own asset pipeline, which takes a .ttf or .otf and emits the .fnt + atlas) or msdf-bmfont. Load them via Assets; they're detected automatically when the FNT file declares a distanceField section.
await Assets.load("fonts/msdf-hero.fnt");
const heading = new BitmapText({
text: "Title",
style: { fontFamily: "msdf-hero", fontSize: 120 },
});
heading.scale.set(2);
MSDF fonts trade CPU rendering time for a custom fragment shader, but remain crisp when scaled up or down.
const paragraph = new BitmapText({
text: "A long wrapped paragraph of bitmap text",
style: {
fontFamily: "Arial",
fontSize: 24,
wordWrap: true,
wordWrapWidth: 300,
lineHeight: 30,
},
});
Standard TextStyle wrapping properties work. Line-height and alignment (align: 'center' | 'left' | 'right') apply to wrapped output.
score.text = `Score: ${value}`;
Updates reposition glyph quads only. No canvas re-draw, no GPU upload. This is why BitmapText is the right choice for every-frame text updates.
pixi.js/text-bitmap in custom buildsWrong (custom build with skipExtensionImports: true):
import { Assets } from "pixi.js";
await Assets.load("font.fnt");
Correct:
import "pixi.js/text-bitmap";
import { Assets } from "pixi.js";
await Assets.load("font.fnt");
Without the side-effect import, .fnt and .xml files aren't recognized by the asset loader; the call silently succeeds but returns raw data instead of a BitmapFont.
resolution on BitmapTextWrong:
text.resolution = 2;
BitmapText ignores resolution and logs a warning. The effective resolution is baked into the BitmapFont at install time. To get higher resolution, install the font with a larger fontSize and scale the text down.
If the font atlas doesn't contain a glyph (e.g., a rare Unicode character), the glyph is silently skipped with no visible error. Text may appear incomplete. For unknown or user-generated content, fall back to canvas Text or HTMLText.
CJK (Chinese/Japanese/Korean), Arabic, and emoji-heavy strings need thousands of glyphs. A bitmap atlas containing all of them exceeds GPU texture-size limits. Use Text or HTMLText for text with unpredictable or very large character sets.