v141 · canvas
Animated Glyphs
ctx.getTextClusters() returns the position, advance, and character range of every user-perceived glyph — including emoji ZWJ sequences and combining characters. This demo uses those positions to animate each glyph independently: wave, scatter, orbit, and typewriter effects, all without layout hacks.
Feature detection: checking…
Note:
getTextClusters() is not available in this browser — falling back to a simple character-split approximation. Use Chrome 141+ for accurate cluster positions (especially emoji and CJK).
getTextClusters() — per-glyph positions
ctx.font = '48px sans-serif';
// getTextClusters() — new in Chrome 141
const clusters = ctx.getTextClusters(text, x, y);
// → [
// { begin: 0, end: 1, x: 16, y: 80, width: 30 }, // 'H'
// { begin: 1, end: 2, x: 46, y: 80, width: 27 }, // 'e'
// { begin: 6, end: 8, x: 156, y: 80, width: 56 }, // '🌍' (2 code units)
// ]
// Animate each cluster independently
function draw(t) {
clusters.forEach((c, i) => {
const offsetY = Math.sin(t + i * 0.5) * 20;
ctx.save();
ctx.translate(c.x + c.width / 2, c.y + offsetY);
ctx.fillText(text.slice(c.begin, c.end), -c.width / 2, 0);
ctx.restore();
});
}
see also
- Grapheme Clusters — original getTextClusters demo
- Selection Rects — hit-test with getSelectionRects
- Font Comparison — cross-font metric differences
- ChromeStatus entry