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).
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
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
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.
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" />
|
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.
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).
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>
|
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>
|
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.
- Explore the W3C's full specification of for SVG; it's quite readable as standards documents go.
- Want more details on SVG? Take a look at these articles and tutorials on developerworks:
- "Introduction to Scalable Vector Graphics" (March 2004)
- "Interactive, dynamic Scalable Vector Graphics" (June 2003)
- "Add interactivity to your SVG" (August 2003)
- "Bring Scalable Vector Graphics to life with built-in animation elements" (June 2003)
- Visit SVG.org, a community Web site that aims to bring all SVG users, developers, and enthusiasts to a single place on the Web.
- Read Wikipedia's entry on SVG. This is a good place to find updated links to many of the tools that support or utilize SVG, including most of those mentioned in this article.
- Visit the OASIS
page for the OpenDocument format. This open format is currently supported by OpenOffice.org, and will become the standard format for KOffice as well. An earlier installment of XML Matters discussed the use of XML in office or word processor documents. Uche Ogbuji also covered the OpenOffice file format in his Thinking XML column here on developerWorks.
- Check out Graphviz, a free software tool for creating circle-and-arrow diagrams (such as hierarchical, directed, or entity-relationship) from an elegant abstract language for describing diagrams. Graphviz includes an SVG export capability.
- Download Batik a Java technology-based SVG Toolkit from Apache.
- Try Skencil, a free software interactive vector drawing application written in Python that supports import and export of SVG (as well as many other formats).
- Find all previous installments of David's XML Matters column on the column summary page.
- Browse for books on these and other technical topics.
- Learn how you can become an IBM Certified Developer in XML and related technologies.

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.



