Web Graphics, Part 2: Scalable Vector Graphics
- SVG and the DOM
- Simple Animations
- Modifying SVG from JavaScript
- Browser Support
In part 1 of this series, Web Graphics, Part 1: The Canvas, we took a look at the <canvas> tag, a new feature described in HTML 5 for drawing PostScript-like graphics in web pages. In this article, we'll consider a related, but very different technology: Scalable Vector Graphics (SVG).
SVG is much older than the canvas. The standard has been developed by the World Wide Web Consortium (W3C) since 1999. It has some similarities to the canvas, in that it uses a PostScript-like model for describing 2D images. Unlike the canvas, however, SVG is declarative rather than imperative. This means that an SVG document is a description of a vector image, rather than being a program used to generate one.
The big advantage of SVG over the <canvas> tag is that you can generate SVG from most vector-drawing programs, whereas you can't easily generate a program that draws on a canvas.
SVG and the DOM
The obvious way to embed SVG images is by using the <img> tag, just as you would embed any other image. Unfortunately, this technique currently works only with Safari and Opera.
The alternative is to use the <object> tag. This approach should work with most browsers, including Internet Explorer if an SVG plug-in is installed. If the browser doesn't support SVG, this mechanism allows transparent failover:
<object data="svg_file.svg" type="image/svg+xml" width="400" height="300"> <img src="rasterized_version.png" alt="Welcome, Lynx user" /> </object>
A section like this will display the SVG content if the browser supports SVG, a rasterized version if it doesn't, or a text string if the browser doesn't even support images. However, inserting SVG in this way removes a lot of its power. It allows static images and simple animations, but nothing especially complex.
Because it's an XML format, SVG can be embedded in any other XML document, which is very convenient for web pages using HTML. If you're using XHTML, you can insert SVG inline. This option makes it load much faster than other image formats, because SVG doesn't require an extra HTTP request.
As an XML format, SVG also gets inserted into the Document Object Model (DOM) tree. Therefore, you can inspect and modify the SVG image JavaScript, just as you would any other XML data in the file.
When you use SVG this way, watch out for a couple of issues. First, some browsers require a file extension of .xml rather than .html for content that contains more than one XML format. Second, you must properly namespace all of your SVG elements. The simplest way of doing this is to add an xmlns attribute to your top-level <svg> tag. For example, you could draw a circle in the middle of a web page like this:
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" baseProfile="full" width="100pt" height="100pt"> <circle cx="50pt" cy="50pt" r="45pt" fill="red" stroke="black" /> </svg>
The xmlns attribute of the <svg> tag tells the XML parser that this tag (and any tags it contains) should be treated as coming from the http://www.w3.org/2000/svg namespace, which defines the SVG standard. The width and height elements here are identical to their canvas counterparts; they reserve a 100-point square for SVG drawing. As with the <canvas> tag, all drawing is clipped to this rectangle.
Note that this namespacing also works in the opposite direction. SVG defines a <foreignObject> tag that performs a role in SVG similar to that of the <object> tag in HTMLreserving some space on the canvas for drawing something else. You can use this technique to embed HTML inside an SVG document:
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" baseProfile="full" width="200pt" height="200pt"> <circle cx="50pt" cy="50pt" r="45pt" fill="red" stroke="black" /> <foreignObject x="20pt" y="20pt" width="60pt" height="60pt"> <body xmlns="http://www.w3.org/1999/xhtml"> <p style="text-align: center">HTML text in an SVG circle!</p> </body> </foreignObject> </svg>
This example draws a circle with a radius of 45 points and then defines a 60-point square box on top of it. This box contains an HTML paragraph. Notice the xmlns attribute of the <body> tag, which tells the XML parser that this element is XHTML rather than SVG. The paragraph is styled with an explicit CSS fragment, but it will also inherit any other relevant CSS styles.
This simple example hides a lot of power. You can extend this approach and use SVG alone for laying out your page, using HTML only for paragraphs of text. HTML describes a rich model for laying out text, but a relatively weak model for positioning elements. This weakness is intentional; HTML is designed for various screen sizes, and the ability of the user agent to modify the layout appropriately for the device is important. On the other hand, SVG has relatively weak support for text, but a rich model for laying out graphics. You can combine the two formats in any way you want.