Note: There are no new demos added at this point and this site is in maintenance mode
start svg demo download
cr4.0 o9.2+ ff3.6 sa5.0

Text Effects

author: Vincent Hardy posted: September 25, 2010 at 03:22 PM categories: yui, text, animation, interactive view comments

Download Video: WebM | MP4 | OGG

Running the demo

Click the 'start svg demo' button on this page. When the page is loaded, you can click anywhere on the canvas to start the demo.

Play time!

I had never got around to play with SVG text as I wanted to and it finally happened with this demo. The demo shows how to access the content of SVG <text> elements and animate individual glyphs.

The demo has a library of 'effects' which are succesively applied to quotes (from

Breaking text into spans

All the effects work similarly. When applied, they first break down the text into a set of text spans which are then animated individually. The target text element (or elements, since the effect can apply to multiple lines of text) is (are) left unmodified and their display property is set to 'none'. The text spans are inserted after the text elemenet and are the target of the different animation effects. The key DOM API method used in the process of computing individual glyph positions is getStartPositionOfChar on the SVGTextContentElement interface (see the specification).

// Compute the different glyph positions and how many characters map to the
// same glyph position (may happen with ligatures).
var p = 0,
    pos = [],
    n = .. /* textContent length */
for (i = 0; i < n; i++) {
    p = text.getStartPositionOfChar(i);
    if (curPos === null ||
        p.x !== curPos.p.x || p.y !== curPos.p.y) {
        curPos = {
            p: {x: p.x + dx, y: p.y + dy},
            n: 1
    } else {
        // Same position, just increase the text run length

Effects and animations

As in several other demos on this web site, the animations are built by extending the YUI 3 JavaScript and CSS library to support SVG. The code also uses a concept of Effect to encapsulate a number of related animations so that they can be manipulated as a single abstraction. For example, the 'opacity-swipe' effect has one animation on the 'fill-opacity' of each glyph, each animation starts when the previous one ends and the user can run the effect which internally starts the first animation, causing the whole animation chain to run. Likewise, the user can use the onBegin and onEnd events on the effect object to invoke specific code when the effect starts or ends.

The following code snippet shows how the 'opacity-swipe' effect applies to the different text spans.

// ...

// toGlyphSpans is a utility method to break down the text in multiple
// elements.
var spans = toGlyphSpans(text),
    n = spans.length,
    anims = [];

// duration, offset and easing a defined somewhere else in the code.s
for (var i = 0; i < n; i++) {
    s = spans[i];
    a = new Animate({
        node: s,
        from: {'fill-opacity': 0},
        to: {'fill-opacity': 1},
        duration: duration,
        easing: easing

for (i = 1; i < n; i++) {
     anims[0].onBegin(anims[i], i * offset);

// The Effect utility provides a way to manipulate a group of animations
// as a single entity.
return new Effect(anims);

Music and Font

Music by Roger Kidd (with all my thanks).

The font used in this demo is "GoodDog" and can be found on Font Squirrel. See the attributions page.

Read and Post Comments