Skip to main content

By clicking Submit, you agree to the developerWorks terms of use.

The first time you sign into developerWorks, a profile is created for you. Select information in your profile (name, country/region, and company) is displayed to the public and will accompany any content you post. You may update your IBM account at any time.

All information submitted is secure.

  • Close [x]

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerworks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

By clicking Submit, you agree to the developerWorks terms of use.

All information submitted is secure.

  • Close [x]

XML Matters: Program with SVG

Make the most of this flexible, portable XML language for graphics

David Mertz, Ph.D (mertz@gnosis.cx), Author, Gnosis Software, Inc.
Photo of David Mertz
David Mertz is a great believer in open standards, and is only modestly intimidated by verbosity. David may be reached at mertz@gnosis.cx; his life pored over at http://gnosis.cx/dW/. Suggestions and recommendations on this, past, or future columns are welcomed. Check out David's book Text Processing in Python.

Summary:  Scalable Vector Graphics (SVG) is an XML format that describes scale-independent graphics, with good support in free software and commercial tools. In this installment, David introduces scripting and animation with SVG, and touches on manipulating SVG through DOM. Because SVG is XML, it lends itself to transformation and/or generation with any of the tools and libraries you might use for XML generally.

View more content in this series

Date:  15 Apr 2005
Level:  Introductory
Also available in:   Russian

Activity:  23392 views
Comments:  

Quite a few powerful vector graphics formats were available before SVG was first imagined around 2001. Postscript and its cousin PDF are widely used in many applications. More application-specific formats include Postscript-based Adobe Illustrator (.ai), CorelDRAW (.cdr), Computer Graphics Metafile (.cgm), Windows Metafile (.wmf), Autocad (.dxf), Hewlett-Packard Graphics Language (.hpgl), WordPerfect (.wpg), and many others. For vector drawings that can even incorporate animation, sound, and interactivity, Macromedia's SWF/Flash is common for content distributed on the World Wide Web.

The main thing that distinguishes SVG from all these other formats is that it is an application of XML. While this means that an equivalent graphic will probably be described considerably more verbosely in SVG than in most other vector formats, it also means that SVG is more versatile to programmatic manipulation. In particular, you can manipulate SVG within Web browsers (or other applications) using ECMAScript and the Document Object Model (DOM). And just as importantly, you can transform and produce SVG using familiar XML techniques like XSLT, or with XML support libraries. You can mix SVG with other XML formats using namespaces. Moreover, you can even stylize SVG using Cascading Style Sheets (CSS). Overall, SVG is a friendly player in XML and Web space.

Beyond being an XML format, SVG is also a fully open standard published by the W3C (see Resources). Unlike most of the vector formats mentioned above, SVG is free of any patent or copyright restrictions, and its specification is fully documented. Like other W3C standards, the specification document itself is copyrighted -- but under W3C's non-restrictive terms that allow for widespread and no-cost reproduction and utilization (for example, no non-disclosure agreements are attached to reading the specification).

Get started

A nice thing about SVG is that you can view it in most modern Web browsers, either natively or through plug-ins. The exact state of support is somewhat in flux, but with the right mojo you should be able to view SVG using Firefox/Mozilla, KHTML (Konqueror and Safari), Opera, or Amaya. Using plug-ins from Adobe or Corel you can even coax Internet Explorer into displaying SVG. A number of standalone viewers for SVG also exist, especially utilizing the Free Software Batik SVG Toolkit (part of the Apache XML project -- see Resources).

In many cases, you will view SVG files as standalone documents. In such instances, these files will be served as MIME type image/svg+xml, and will generally have the file extension .svg. Gzip compressed SVG files should have the extension .svgz, and are directly supported by most SVG-enabled tools. An SVG file is just an XML file with an appropriate DTD. You will see this declaration in several examples below.

However, perhaps even more commonly, you can embed an SVG document within a larger document, particularly within an XHTML page. Other compound XML formats, such as OASIS OpenDocument, also do (or will support) embedding SVG within them. You can include an SVG graphic within an (X)HTML page in three ways:

  • Through the <object> tag
  • Through the <embed> tag
  • As an embedded namespace

Unfortunately, exactly which of these actually works depends on your browser and version. For example, I created the following XHTML document (with a doctype intended to support namespace nesting):


Listing 1. XHTML document (svg-nested.html)

<?xml version="1.0" standalone="no"?>
<!DOCTYPE html PUBLIC
    "-//W3C//DTD XHTML 1.1 plus MathML 2.0 plus SVG 1.1//EN"

"http://www.w3.org/2002/04/xhtml-math-svg/xhtml-math-svg.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
  <title>SVG as embedded object and nested namespace</title>
</head>
<body>
<h2>Object tag</h2>
<object type="image/svg+xml" data="standalone.svg">
Your browser is currently unable to display SVG images.
</object>
<h2>Nested namespace</h2>
<svg:svg version="1.1" width="5cm" height="4cm"
      xmlns:svg="http://www.w3.org/2000/svg">
  <svg:title>Four rectangles</svg:title>
  <svg:rect x="0.5cm" y="0.5cm" width="2cm" height="1cm"/>
  <svg:rect x="0.5cm" y="2cm" width="1cm" height="1.5cm"/>
  <svg:rect x="3cm" y="0.5cm" width="1.5cm" height="2cm"/>
  <svg:rect x="3.5cm" y="3cm" width="1cm" height="0.5cm"/>
  <!-- Show outline of canvas using 'rect' element -->
  <svg:rect x=".01cm" y=".01cm" width="4.98cm" height="3.98cm"
       fill="none" stroke="blue" stroke-width=".02cm" />
</svg:svg>
<h2>Embed tag</h2>
<embed id="svg3" src="standalone.svg" />
</body>
</html>

Safari/KHTML does the best of the browsers I tried. Even so, the results are better if the file is named with an .html extension than with an .xml extension. Overall, <embed> seems like the most successful approach. You might see the document rendered something like this:


Figure 1. Web browser displaying svg-nested.html
Web browser displaying svg-nested.html

Incidentally, the examples I present in this article are rather simple combinations of basic shapes, text, colors, and such -- but SVG is fully capable of representing complex and attractive drawings. Just to comfort readers, here is the famous PostScript tiger picture that's included with Ghostscript nd other tools, rendered using SVG (I only touched up its overall sizing):


Figure 2. Web browser displaying tiger image as SVG
Web browser displaying tiger image as SVG

Features of SVG documents

The prior XHTML example (see Listing 1) showed you a very basic SVG drawing. The external file that is referenced (standalone.svg) contains the same elements as those embedded in the XHTML, minus the extra namespace qualifier in the tags. SVG gives you a number of graphic primitives, and each primitive has various XML attributes that further specify the graphic: color, size, position, fill, outline, and so on. However, explicit graphic primitives, such as ellipses, rectangles, or polygons -- or more sophisticated <path> elements that might include cubic or quadratic Bezier curves -- are often included within <g> elements to group several primitives together. The nice thing about a <g> group is that you can scale, move, style, and otherwise modify it as a whole. Modifications to the group generally apply to the collection of shapes within them (including nested <g> groups). This is especially useful when SVG documents are scripted.

All the way down

One thing to notice about SVG documents is that they are not really XML all the way down. Syntactically, SVG is indeed XML, but a significant portion of the information content of an SVG drawing is contained within comma- and space-delimited data inside SVG attributes. When I mention information content, I am not speaking of XML Infoset, but only of the more informal concept of What does it contain? Doing it this way is a reasonable compromise, since using child elements for every point or handle that defines a curve would make SVG even more verbose. But XML-level processing techniques like XSLT can thereby not really do much with path data. For example, this is a quadratic Bezier path element:

<path d="M200,300 Q400,50 600,300 T1000,300"
      fill="none" stroke="red" stroke-width="5"  />

And this is a polygon describing a pentagram:

<polygon fill="red" stroke="blue" stroke-width="10"
          points="350,75  379,161 469,161 397,215
                  423,301 350,250 277,301 303,215
                  231,161 321,161" />

Add style

Earlier, I mentioned that you can use CSS selectors and syntax to modify the appearance of SVG drawings. As with HTML and other CSS-supporting formats, you can either specify CSS information inline or as a reference to an external stylesheet. A very simple example of inline CSS is:


Listing 2. A simple CSS example (inline-styled.svg)

<?xml version="1.0" standalone="no"?>
<!-- By ref:
  <?xml-stylesheet href="mystyle.css" type="text/css"?>
-->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"

"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="10cm" height="5cm" viewBox="0 0 1000 500"
    xmlns="http://www.w3.org/2000/svg" version="1.1">
  <defs>
    <style type="text/css"><![CDATA[
      rect {
        fill: red;
        stroke: blue;
        stroke-width: 3
      } ]]>
    </style>
  </defs>
  <rect x="200" y="100" width="600" height="300"/>
</svg>

While you can certainly style an entire tag using CSS, you'll probably find that using class selectors is a better use of CSS and SVG. For example, you might define a variety of types of rectangles within a stylesheet, then attach a class XML attribute to each one in your drawing, rather than repeat the full list of colors, fills, strokes, and other attributes that you define for the class. By simply changing the stylesheet, you can change the overall look of your diagram to make it more suitable for a different context.

Reuse elements

Beyond the use of CSS, Listing 2 illustrates another nice feature of SVG: You can include predefined content within an SVG document -- content that is defined either within or outside of the document being rendered.

One way to use predefined content as part of an SVG drawing is with the <image> element. In concept, <image> in SVG is very similar to <img> in HTML: The element simply instructs the rendering client to draw the content of an external image -- which may itself be either SVG or a raster image in JPEG or PNG format -- inside the current SVG context. You can size and position the external image almost as if it were a regular graphic element. For example:


Listing 3. Include an external SVG drawing within the current image

<image x="200" y="200" width="100px" height="100px"

xlink:href="http://example.org/external.svg">

Perhaps more interesting than the <image> tag are the complimentary elements <defs> and <use>. The first, which you saw with the CSS example, lets you create SVG elements that are not directly rendered when defined -- normally the SVG rendering model draws each object in exactly the order it occurs within an SVG document, each overlaying the last. But <style> is a bit atypical in that you cannot really render it later, per se.

You can include whatever graphic elements you like in a <defs> section, including <g> groups and <symbol> elements (symbols are similar to groups; this article does not have room to address that distinction). Outside the definition, you can <use> the graphic elements defined in a <defs> section -- even the <defs> section of an external SVG document. For example:


Listing 4. Using predefined graphic elements

<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"

"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="7cm" height="3cm" viewBox="0 0 70 30" version="1.1"
     xmlns="http://www.w3.org/2000/svg"
     xmlns:xlink="http://www.w3.org/1999/xlink">
  <desc>'use' with a 'transform' attribute</desc>
  <defs>
    <rect id="MyRect" x="0" y="0" width="40" height="5"/>
  </defs>
  <use xlink:href="#MyRect" transform="translate(10,23) rotate(-30)" />
  <use xlink:href="#MyRect" transform="translate(20,3) rotate(30)" />
  <use xlink:href="http://example.org/foo.svg#OtherRect"/>
</svg>

In Listing 4, the same defined rectangle is rendered with two different transformations, then an externally defined element is also rendered (the id name suggests it is also a rectangle, but you do not know for sure from this fragment -- in fact, the external content might change between renderings).


Animation and scripting

As I mentioned, SVG is scriptable using ECMAScript. In principle, this lets SVG documents interact with user actions. To aid the Web-application space, SVG also contains an HTML-like <a> element for hyperlinks. A simple interaction in SVG modifies a document based on mouse clicks on particular graphic elements. The example in Listing 5 is trivial, but you could easily let an SVG graphic respond, for example, to clicks on regions of a map or objects in a flow chart:


Listing 5. Let an SVG shape respond to clicks

<svg>
  <title>ECMAScript function for an onclick event</title>
  <desc>Simplified from 
   http://www.w3.org/TR/SVG11/images/script/script01.svg</desc>
  <script type="text/ecmascript"> <![CDATA[
      function circle_click(evt) {
      var circle = evt.target;
      var currentRadius = circle.getAttribute("r");
      if (currentRadius == 100)
        circle.setAttribute("r", currentRadius*2);
      else
        circle.setAttribute("r", currentRadius*0.5);
    } ]]>
  </script>
  <!-- Act on each click event -->
  <circle onclick="circle_click(evt)" cx="300" cy="225" r="100" fill="red"/>
</svg>

You can also use ECMAScript and the DOM to animate SVG graphics. For example, the code in Listing 6 produces a nice looking effect of text that grows and changes opacity:


Listing 6. Animate SVG with JavaScript

<svg viewBox="0 0 400 200"
     onload="StartAnimation(evt)" version="1.1"
     xmlns="http://www.w3.org/2000/svg">
  <script type="text/ecmascript"><![CDATA[
    var txt, step=0;
    function StartAnimation(evt) {
      txt = evt.target.ownerDocument.getElementById("Text");
      ShowAndGrowElement();
    }
    function ShowAndGrowElement() {
      step = step+1;
      if (step > 200) return;
      // Scale text string gradually until it is 20 times larger
      txt.setAttribute("transform", "scale("+ step/10 +")" );
      // Make the string more opaque
      txt.setAttribute("opacity", step/200);
      // Call ShowAndGrowElement again 50 milliseconds later.
      setTimeout("ShowAndGrowElement()", 50)
    }
    window.ShowAndGrowElement = ShowAndGrowElement
  ]]></script>
  <g transform="translate(50,150)" fill="red" font-size="7">
    <text id="Text">SVG</text>
  </g>
</svg>

Pure SVG scripting

Using ECMAScript gives you full programming flexibility, but if all you want is animation, SVG has <animate> and related tags (such as <animateMotion> or <animateColor>). These are quite flexible, and allow you to animate each element of an SVG document independently and in various ways. For example, the code in Listing 6 produces the same grow-and-become-opaque effect as the technique shown in Listing 5:


Listing 6. Animating with SVG alone

<svg viewBox="0 0 400 200" xmlns="http://www.w3.org/2000/svg">
  <g transform="translate(50,150)" fill="red" font-size="7">
    <text id="Text">SVG
      <animateTransform attributeName="transform" attributeType="XML"
              type="scale" from="0" to="20" begin="0s" dur="10s"
              fill="freeze" />
      <animate attributeName="opacity" attributeType="CSS"
               from="0" to="1" begin="0s" dur="10s" repeatCount="1" />
    </text>
  </g>
</svg>


Conclusion

This article has touched on just a few basics of the SVG format. Writing it has been enough to make me quite excited about SVG as a format. The Web really needs a vector format for efficiently conveying complex graphics in a scale-independent way. Throwing in scripting, animation, linking, and all the rest just makes SVG that much more useful. And luckily, most Web browsers now have pretty good SVG support, so no real obstacle exists to deploying graphics and simple Web applications based on SVG.


Resources

About the author

Photo of David Mertz

David Mertz is a great believer in open standards, and is only modestly intimidated by verbosity. David may be reached at mertz@gnosis.cx; his life pored over at http://gnosis.cx/dW/. Suggestions and recommendations on this, past, or future columns are welcomed. Check out David's book Text Processing in Python.

Report abuse help

Report abuse

Thank you. This entry has been flagged for moderator attention.


Report abuse help

Report abuse

Report abuse submission failed. Please try again later.


developerWorks: Sign in


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Select information in your profile (name, country/region, and company) is displayed to the public and will accompany any content you post. You may update your IBM account at any time.

Choose your display name

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


Rate this article

Comments

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=XML, Web development
ArticleID=59063
ArticleTitle=XML Matters: Program with SVG
publish-date=04152005
author1-email=mertz@gnosis.cx
author1-email-cc=dwxed@us.ibm.com