SVG and Typography: Animation
In the last part of our exploration of SVG and Typography, we turn our attention to effects with animated type, exploiting SVG declarative animation features.
Instead of just using individual samples showcasing each technique, I decided to finish these series with a summarizing work. I recommend that before we start you take a look of the whole animation here.
As we create the animation piece by piece, we will explore the following techniques, a basic canon of type animation for the Web:
The central piece is based on a Westvaco Illustrations work by designer visionary Bradbury Thompson, a remarkable man who preferred not to make empty praise of an idea, but rather make sure every opinion was expressed through compelling work, making the idea's value evident by itself, not by adjectives attached to it.
I hope some of Thompson's pragmatism is reflected in this series. It is certainly needed when technologies like SVG are artificially inflated by adjectives ("paradigm-shifting-ground-breaking-replaces-your-dog-and-then-some"), which is a certain recipe for disappointment.
In the very beginning of our animation we animate the color and opacity of the
title "SVG and Type: Animation" to make it blend with the
background. In order to give a subtle complexity to the animation, we mix two
different techiques: The word "and"
varies from a light gray (#797979) to a final, darker gray (#888888), while the
rest of the title just changes its opacity from 1 (100%) to 0.
Varying the color of text over time is a simple process that can be
achieved by including an animate sub-element of the text (or tspan)
element as shown in Listing 1.
Attributes are truly self-documenting: the animation takes one second, starts
one second after the element with id "startmeup" is clicked, and
varies the attribute fill (which as you remember from installment 1 of this
series controls color of the text). The values used are the two grays needed.
<tspan style="font-size:40;fill:#797979">and
<animate attributeName='fill' values='#797979;#888888' dur='1s'
fill='freeze' begin="startmeup.click+1"/>
</tspan"
Note that the values element could contain any number of
steps, or intermediate colors, and the SVG interpreter would cycle through them;
for example, it could have been
values='#797979;#08FF21;#FF0000;#FFFF13' to make a rainbowy
effect. However, it is important to keep in mind that just because it is easy to
do, it doesn't necessarily mean it is a good idea. As with so many things,
when animating color, subtlety is best most of the time.
All animate attributes are straight-forward except perhaps for the
fill attribute. Note this does not refer to the fill of the SVG (color)
element but to what happens once the duration of the animation is over. By
specifying the freeze value, we declare the last stage of the animation
is held and visible (i.e. the animation simply stops at the end, instead of
dissapearing or restarting).
Animating opacity is just as simple as animating color or
any value of an SVG element for that matter: include an animate
element, specify the attribute/CSS property you want to animate on the parent,
and specify your stop values. See Listing 2.
<text x="400" y="274" style="font-size:72;fill:#CCCCCC">SVG
<animate attributeName='opacity' values='1;0' dur='1s'
fill='freeze' begin="startmeup.click"/>
</text>
Listing 2. Animating Opacity
We can use this technique to animate not only an element (the text) but a
complex group of objects (e.g one of our fishes), as shown in Listing
3. Similarly, we can set the beginning of the animation to be anything, from a
set value in time (e.g. begin="20s") to an user event
(e.g. startme.click) to a relative event on another element (e.g. bait.end) to a
mixture of them (e.g. bait.end+3)
<g>
<code>
<animate attributeName='opacity' values='0;1' dur='2s'
fill='freeze' begin="bait.end"/>
</code>
...
</g>
Listing 3. Animating Opacity on a group/relative start
Apart from the animate element, another option available is to
actually set a property to a particular value on any given time. For example, if
we wanted a text to dissapear instantly, twenty seconds after we click
the start button we use the following code (Listing 4):
<set attributeName="opacity" to="0" begin="startmeup.click+20"/>
Listing 4. set element
Color and opacity effects with type are a common design element on the Web, especially for decorative purposes. However, this doesn't mean that the only place for animation and type is brochureware featuring the much-exhausted company name tweening from black to white. On the contrary, type animation can be a unique art tool and a compelling touch in user interfaces. In the present example you can see it at use for artistic purposes, in previous articles (and surely on future ones) you can see the techniques applied as UI enhancements.
One positive aspect of SVG's XML nature is the ability to play well with your
open source hacking skill-set. Even as a beginner developer it is easy to create programs that output
text such as the one needed for our next trick, a typewriter effect.
The typewriter effect we will use is based on animating references to
text, which as you may remember, is achieved via tref. Using
tref you populate your text element with a
predefined piece of text.
Usually, using tref is helpful to encapsulate all text at the top of the SVG so
it can be easily changed to other languages or edited. In
this case we will use it a little differently: we will define many text elements
and make one tref go through all of them. We will animate through
strings like "A", "An",
"Ani", "Anim" and so on, creating the illusion
of adding a letter at a time.
First, we describe at the top of our SVG document, the definitions of the strings we will animate through (Listing 5):
<defs>
<text id='t-1'> </text>
<text id='t0'>A</text>
<text id='t1'>An</text>
<text id='t2'>Ani</text>
<text id='t3'>Anim</text>
<text id='t4'>Anima</text>
<text id='t5'>Animat</text>
<text id='t6'>Animati</text>
<text id='t7'>Animatio</text>
<text id='t8'>Animation</text>
<text id='t9'>Animation </text>
<text id='t10'>Animation i</text>
<text id='t11'>Animation in</text>
<text id='t12'>Animation in </text>
<text id='t13'>Animation in S</text>
<text id='t14'>Animation in SV</text>
<text id='t15'>Animation in SVG</text>
<text id='t23'>Animation in SVG, </text>
<text id='t24'>Animation in SVG, s</text>
...
</defs>
Listing 5. Typewriter (defs)
Then, we use the animate element to cycle through each definition,
by varying the xlink:href attribute through each of the ids.
<text x="40" y="110">
<tref>
<animate attributeName='xlink:href'
values='#t0;#t1;#t2;#t3;#t4;#t5;#t6;#t7;#t8;#t9;#t10;#t11;#t12;
#t13;#t14;#t15;#t24;#t25;#t26;#t27;#t28;#t29;#t30;#t31;
#t32;#t33;#t34;#t35;#t36;#t37;#t38;#t39;#t40;#t41;#t49;
#t50;#t51;#t52;#t53;#t54;#t55;#t56;#t57;#t58;#t59;#t60;
#t61;#t62;#t63;#t64;#t65;#t66;#t67;#t68;#t69;#t70;#t71;
#t72;#t73;#t74;#t75;#t76;#t77;#t78;#t79;#t80;#t81;#t82;
#t83;#t84;#t85;#t86;#t87;#t88;#t89;#t90;#t91;#t92;#t93;
#t94;#t95;#t96;#t97;#t98;#t99;#t100;#t101;#t102;#t103;#t104'
dur='10s' fill='freeze' begin="startmeup.click"/>
<animate id="a1" attributeName='x' values='40;0' dur='4s'
fill='freeze' begin="startmeup.click+8"/>
</tref>
</text>
Listing 6. Typewritter (animate)
At first
it may be surprising that you can animate something like this, but as you can
see, it is an interesting source of flexibility. I suggest you try animating other
traditionally "static" attributes such as the text's font for fun,
as well as for getting a better appreciation of the generality of SVGs animation model
(<animate attributeName='font-family' values='Arial;Verdana;Times'
dur='10s' begin="startmeup.click"/>)
We also have animated the position of the text by varying the x attribute of the text element, but this
animation only starts a little later (8 seconds later actually) so the overall
effect is initially only that of typewriting and then it gets mixed with sliding.
Now, typing a hundred strings for the typewriter animation is tedious, but that is where the text nature of SVG comes in handy. The following Perl script produces the necessary definitions for replicating this effect with any string:
$s = "Put your string here.";
$a = "<animate id='a1' attributeName='xlink:href' values='";
for($i=0; $i < length $s; $i++)
{
print "<text id='t".$i."'>".substr($s,0,$i+1)."</text>\n";
$a .= "#t" .$i. ";";
}
$a .= "' dur='5s' fill='freeze' begin='YOUR_START_BUTTON.click'/>\n";
print $a;
Listing 7. Perl code to generate typewriters
Of course, by pointing out this solution, I don't mean to suggest SVG is unique in its capacity to make easy typewriter effects, or even that Listing 6 is the best way to make them in SVG (actually Stefan Goesnner and Michel Hirtzler have very general javascript-based SVG components to do this).
What I do mean to suggest is a certain consistency between SVG's XML nature and the hacking mechanisms so valued in the open source community: open the hood, reuse your knowledge of open technologies to figure how things are working, and then slap in a quick solution using other known OS tools.
![]()
A less common effect used in the first half of our animation is making text move over a path. We use it to make the second line of text follow the same wave as a fish.
As you may remember from previous articles in these series, putting text on a
path is achieved by using a textPath element as shown in Listing 8:
<text>
<textPath xlink:href="#wave1">
but animation is more, says the artist: it's the fish
in the water. Motion creates emotion.
</textPath>
</text>
Listing 8. Text on a Path
Another property we discussed previously when analyzing characters was the
startOffset, a value that alters the position of the text by
modifying where should it start. In this case a startOffset of 0 would mean the
text starts at the beginning of the path.
Putting these two elements of past articles (textPath and
startoffset) together with our animate element we can make
text flow across the path by animating its offset, as illustrated in Listing 9:
<textPath xlink:href="#wave1" startOffset="-610">
but animation is more, says the artist: it's the fish
in the water. Motion creates emotion.
<animate id="a2" attributeName='startOffset'
values='-610;25' dur='5s' fill='freeze' begin="a1.begin"/>
</textPath>
Listing 9. Moving text accross a Path
In the interest of honesty, it must be pointed out that the other half of
this effect, the definition of the path itself (<path
id="fishfloat" d="M0 0 C11.145 12.2554 11.224 13.7919 13.333 12.6364z"/> ), is not something
you can comfortably expect to code by hand. To draw the paths you will have to use either a commercial tool like Adobe
Illustrator 10, Jasc WebDraw, or try one of the emerging online SVG drawing
tools.
At the end of the animation we use the effect again, to move the fishing
string that reads "use animation for bait". Only this
time we use a different path, and combine it with a decaying opacity to convey
the notion of a time lapse (Listing 10).
<text x="600" y="60" style="opacity:0">
<set attributeName="opacity" to="1" begin="rowing1.end+3"/>
<animate id="dissapearRod" attributeName='opacity' values='1;0' dur='4s'
fill='freeze' begin="rowing1.end+4"/>
<textPath xlink:href="#rod1" startOffset="0">
use animation for bait.use animation for bait.use animation for bait.use
animation for bait.
<animate attributeName='startOffset' values='610;-80' dur='5s'
fill='freeze' begin="rowing1.end+3"/>
</textPath>
</text>
Listing 10. Moving fishing string text
There are many other elements of this animation that I
have not described directly in the article. The reason for this is that they are
either outside the core of the discussion (e.g. "how to draw the
fish") or
because their theory is explained in the three previous articles of these
series.
Among the elements based on previous articles are
In this series we have explored the relationship of typography and SVG from a variety of perspectives, from purely technical issues related to characters and portability, to creative issues dealing with color, composition, and effects.
I hope you find these articles useful. Please feel free to drop me a line with questions any time.
XML.com Copyright © 1998-2006 O'Reilly Media, Inc.