In Part 1 of this article we examined Scalable Vector
Graphics (SVG) as an XML-based image format. In Part 2, we investigate SVG’s
dynamic and interactive nature and delve into the scripting techniques that
make SVG come to life.


Getting started

To get started with SVG
(and in order to view the examples in this article) you will need to download
the SVG viewer from Adobe.

The fully functional
examples shown in this article can be viewed here:

Example A

Example B

Example C

Example D

Example E


Figure A shows three frames from an animated button created with
SVG. In the first frame, the button opacity has been reduced to 70 percent. The
second frame shows the end result when the user moves the mouse over the button
area. The animated effect triggered by the hovering mouse pointer increases the
button’s opacity gradually, until it is at its full opacity. The third frame
displays the last frame of an animation triggered when the button is clicked.

Figure A

Animated button

The button consists of two
rectangles and a text element. The first rectangle is the blue rectangle that
is visible under the text. All of these elements are nested within an anchor
tag. The SVG <a /> tag is similar to the <a> tag in HTML. Clicking
the nested shape replaces the current page with the URL in the xlink:href
attribute. The basic structure for the example in Figure A is as follows:

<a xlink:href="http://www.mysite.com" id="anchor">
    <rect id="blueRect" />
    <text id="whiteText">Click me</text>
    <rect id="glassRect"  style="fill-opacity:0" />
</a>

In HTML, rollovers are
achieved through CSS or JavaScript functions. In contrast, the rollover
mechanism is built into the SVG standard. For example, a simple rollover looks
like this:

<rect fill="blue">
<set attributeName="fill" from="blue" to="red" 
begin="mouseover" end="mouseout"/>
</rect>

The <set> tag is
used to change an element’s attribute from one state to another. In the example
above, the <set> tag is nested in a rectangle, which changes color from
blue to red when the user moves the mouse over it.

To change an element’s CSS
properties, you use attributeType=”CSS”,
like this:

<set attributeName="filter" attributeType="CSS" 
to="url(#DropShadow)" begin="mouseover" end="mouseout"/>

The drop shadow effect in
Figure A is accomplished with a combination of SVG filters. The feGaussianBlur creates the drop shadow’s
fuzziness, while the feOffset’s dx
and dy
attributes determine the direction and depth of the drop shadow.

<filter id="DropShadow">
      <feGaussianBlur stdDeviation="2" />
      <feOffset in="blurredAlpha" dx="2" dy="2" />
</filter>

Event handling

Let’s assume we want the
button to behave consistently whether the user has moved the mouse over the
text or the rectangle part of the button. The first solution is to include a
second rectangle that has zero opacity. This invisible rectangle is like a
sheet of glass placed over the button to catch animation events.

The second solution is to
group all of the button’s subelements together by nesting them inside an anchor
tag and routing the events to subparts of the button. This <set> tag
will change the text’s color regardless of whether the user’s mouse is over the
button’s rectangle or the text:

<set attributeName="fill" to="#d0f0f0" 
begin="anchor.mouseover" end="anchor.mouseout"/>

Mouse events

The SVG standard provides
a mechanism for using a mouse to start an animation. In the code snippet below,
the animation starts two seconds after the rectangle is clicked and lasts for
two seconds. The rectangle’s opacity fades from full opacity to a fifth of its
original value.

<rect>
<animate attributeName="opacity" from="1" to="0.2" 
begin="click + 2s" dur="2s" fill="freeze" />
</rect>

Scripts can be used to
achieve the same, or even more complex, fine-tuned effects. The simplest way to
call a script is via the shape’s onclick
attribute.

<rect onclick=" startAnimation()" />

The startAnimation() function initializes animation
variables and sets up the animation timer. The interval value refers to the number of milliseconds between each
frame.

timerId = setInterval('doFrame()', interval);

The doFrame() function is called once per frame and is responsible for creating
the animation effect. The rectangle’s opacity and movement is animated by
gradually changing the currentValue
variable.

item.getStyle().setProperty("fill-opacity", currentValue);
item.setAttribute("x", currentValue*10);

Manipulating the document

In Figure B, when the user clicks on a rectangle it is displayed in
front of the other two rectangles. This example uses the appendChild() method to change the visual order of elements by changing their
positions in the document object model (DOM). This is a useful technique for
creating layered effects and tabbed widgets.

Figure B

Visual order

Figure C

DOM manipulation

Figure C is an example of DOM manipulation, in which the user
creates dynamic text by clicking the blue button. Use the createElement() method to create a new blank node, set
the new node’s attributes, and add the node to the DOM using appendChild().

svgdoc=evt.target.ownerDocument;
node=svgdoc.createElement("text");
node.setAttribute("id","text" + count);

The most recently added
text element gets deleted when the user clicks one of the text elements. The
code gets a handle on the correct element using getElementById(), then uses its parent’s removeChild() method to delete the
element.

object=svgdoc.getElementById("text" + count);
var root=object.getParentNode(); 
root.removeChild(object);

Figure D

Draw a line

Figure D displays another nifty use for DOM manipulation. The user
gets to draw lines by clicking, dragging, and then unclicking at the end of the
line. The SVG document defines a line that is invisible initially because its
start and end x and y values are equal to zero.

When the user first clicks
the SVG, the line’s x1 and y1 values are set to the mouse x and y values. When the user starts dragging the mouse, the x2 and y2 values are set to the current mouse x and y values. The line
is redrawn dynamically as the user moves the mouse. When the user unclicks the
mouse, the line is redrawn in its final position.

Figure E

Text wrapping

Text wrapping is
potentially one of SVG’s trickiest techniques. Figure E displays a solution in which text is wrapped when it
reaches the end of a line. Check out this example by loading Example E into a browser. Simply move the mouse over the box
and start typing. The text wraps when the end of the line is reached, or when
the enter key is pressed.

Two methods create the
text wrap functionality. The textEvent(evt)
method handles the capturing of text as the user types on the keyboard, while newRow() moves to the next row in the
sequence.

In the textEvent(evt) method, String.fromCharCode(key)
captures the latest character typed by the user. The line containing obj.firstChild.setData(str) updates the current row with the
latest string. Note that we call the firstChild()
method to get a handle on the text, which is a child of the text node. Once we
have a handle on the text, it is possible to use setData() to replace the text.

The key to this technique
is to know when to wrap the text. This is accomplished by calculating the
length of the text using obj.getComputedTextLength() and ensuring that the current text’s
length does not exceed the maximum width allowed per line of text.

Batik

Batik is an Apache XML subproject that provides a software
platform for the generation, manipulation, and viewing of SVG documents. After
downloading Batik from the Apache Web site, unzip it onto your file system.

Batik also has its own SVG
browser, called Squiggle. To install Squiggle, navigate to the Batik directory
on your system and type the following into the command line:

java -jar batik-squiggle.jar.

There are several useful
modules bundled with Batik, including the rasterizer module, which allows for
the automatic transformation from SVG format to JPEG or PNG. The following
command line converts a directory containing SVG documents into JPEGs and
places the resulting files into the output directory:

java -jar batik-rasterizer.jar -m image/jpeg -q 0.8 -d output/ input/*.svg

Bottom line

SVG adds a new level of interaction to the Internet and related applications.
Because SVG files are small and portable, they are perfect for applications
that need to transmit data to a user in a dynamic, graphical form.