This is a quick start guide to using the SVG Web toolkit.
SVG, or Scalable Vector Graphics, is an open web standard that makes it easy to add interactive vector graphics to your web pages. Just like HTML gives you simple tags such as <form> or <table> to add to your web pages, SVG gives you such graphical tags as <circle> or <rect> for a rectangle. Working with SVG is very similar to working with HTML -- you use JavaScript to animate things, CSS (Cascading Style Sheets) to add style, etc. A good introduction to SVG can be found at www.svgbasics.com (note: if you know of a good SVG tutorial that introduces SVG markup, scripting, and SMIL please contact us!)
SVG Web is a JavaScript library which provides SVG support on many browsers, including Internet Explorer, Firefox, and Safari. Using the library plus native SVG support you can instantly target ~95% of the existing installed web base.
Once dropped in you get partial support for SVG 1.1, SVG Animation (SMIL), Fonts, Video and Audio, DOM and style scripting through JavaScript, and more in about a 60K library. Your SVG content can be embedded directly into normal HTML 5 or through the OBJECT tag. If native SVG support is already present in the browser than that is used, though you can override this and have the SVG Web toolkit handle things instead. No downloads or plugins are necessary other than Flash which is used for the actual rendering, so its very easy to use and incorporate into an existing web site.
SVG Web can either be used from HTML and JavaScript web pages or pure Flash and Flex applications. This Quick Start guide only details using the SVG Web toolkit from HTML and JavaScript web pages rather than from pure Flash or Flex applications.
Please keep in mind that SVG Web is in alpha. If you find something file an Issue.
If you are using SVG Web, make sure to tell the community about it on our "Projects Using SVG Web" Wiki page!
At any time while you work through this Quick Start guide the following resources are available to you:
SVG Web comes with a small embedded web server that you can run locally in order to quickly get started. When developing, you can't simply load things from file://
URLs as some browsers and Flash have issues when loaded from the local file system. Instead, you must load things through http://
; the small bundled web server makes this easy. You must have Java installed to run it.
To run the web server simply go into the SVG Web distribution and type the following into a command line:
java -jar src/tools/webserver.jar
By default this will start a local webserver on 127.0.0.1
on port 8080.
You can optionally provide other local IP addresses if you want to listen on multiple IP addresses; this can be useful, for example, if you have a Parallels Virtual Machine instance running Windows XP, and you want to locally access your files while working. By default Parallels installs a loopback IP address on 10.211.55.2
. You can use the optional -h
flag to start on multiple IP addresses with the embedded web server:
java -jar src/tools/webserver.jar -h 127.0.0.1 10.211.55.2
This would start up the local web server on 127.0.0.1:8080
and 10.211.55.2:8080
.
http://127.0.0.1:8080/samples/javascript-samples/helloworld.html
. You should see two SVG images side by side, with a blue circle and the text "Hello World From Embedded SVG!" and "Hello World From An SVG File!".You're now ready to start playing with SVG and the SVG Web library! Let's start by delving into the helloworld.html sample. From now on we will assume that you are running the local web server.
To use SVG Web, you must drop a script
tag into your HTML page. This must be the first script tag on your page:
<script src="svg.js"></script>
<!-- Further script tags should follow after SVG Web's script tag -->
<script src="foobar.js"></script>
<script>alert('hello world')</script>
If your HTML page and the SVG Web library are in different directories, you also must provide a data-path
HTML 5 attribute pointing to where the SVG Web files are. This helps SVG Web figure out where to load up the extra files it needs.
For example, if the SVG Web library is in ../../src
, then you would have the following script
tag:
<script src="../../src/svg.js" data-path="../../src"></script>
There are currently two different ways to add SVG to your page using SVG Web:
The helloworld.html sample illustrates how to do both. Let's step through this file to see the two different ways to embed SVG.
SVG Web allows you to directly embed SVG into your HTML page, even for normal, non-XHTML pages.
To directly embed SVG, you place your SVG into a SCRIPT block and set the type
attribute to image/svg+xml
. This is valid HTML 5 syntax for embedding data blocks and is necessary for your SVG to be parsed correctly. Here is an example direct embed from the helloworld.html file:
<h1>This is some HTML here!</h1>
<script type="image/svg+xml">
<svg
width="200" height="200"
style="background-color: #D2B48C; display: block; margin-bottom: 5px;"
id="embeddedSVG">
<g
id="myGroup"
fill="blue"
style="font-size: 18px; text-anchor: middle; font-family: serif;">
<circle
id="myCircle"
cx="100" cy="75" r="50"
stroke="firebrick"
stroke-width="3" />
<text x="100" y="155">Hello World</text>
<text x="100" y="175">From Embedded SVG!</text>
</g>
</svg>
</script>
When direct embedding SVG, you should leave off the XML declaration and SVG DOCTYPE, such as <?xml version="1.0"?>
. You also don't need to declare the XLink or SVG namespaces as those will be defaulted and assumed.
You can also embed your SVG using an OBJECT tag. This is useful when you want to keep your SVG assets separate from your web page.
In an ideal world we would use a single OBJECT tag; unfortunately, we have a slightly more complex syntax to help Internet Explorer and have to repeat the OBJECT tag twice with slightly different attribute names. Here is an example from our helloworld.html sample:
<!--[if !IE]>-->
<object data="../svg-files/helloworld.svg" type="image/svg+xml"
width="200" height="200" id="mySVGObject"> <!--<![endif]-->
<!--[if lt IE 9]>
<object src="../svg-files/helloworld.svg" classid="image/svg+xml"
width="200" height="200" id="mySVGObject"> <![endif]-->
<!--[if gte IE 9]>
<object data="../svg-files/helloworld.svg" type="image/svg+xml"
width="200" height="200" id="mySVGObject"> <![endif]-->
</object>
In general, you should copy the above syntax exactly and modify the following:
src
and data
attributes to point to where your SVG file is on all OBJECT tags.width
and height
attributes on all OBJECT tags to the desired width and height.id
or class
attribute, make sure it is on all OBJECT tags.Note that your SVG file must be served from the same host as the page is served from.
It's also important that your SVG file have an XML declaration on the first line as well as all namespaces declared; basically this file must be a valid XML file, which is a bit different than when you directly embed SVG into a web page. The helloworld.svg file:
<?xml version="1.0"?>
<svg
version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="200" height="200"
style="background-color: #D2B48C;">
<g
id="myGroup"
fill="blue"
style="font-size: 18px; text-anchor: middle; font-family: serif;">
<circle
id="myCircle"
cx="100" cy="75" r="50"
stroke="firebrick"
stroke-width="3" />
<text x="100" y="155">Hello World</text>
<text x="100" y="175">From An SVG File!</text>
</g>
</svg>
Both the direct embed and OBJECT options can provide optional fallback content; see the User Manual for more details.
The SVG in the helloworld.html sample provides a nice basic overview of SVG, so we will quickly review it here. Here is the SVG again:
<?xml version="1.0"?>
<svg
version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="200" height="200"
style="background-color: #D2B48C;">
<g
id="myGroup"
fill="blue"
style="font-size: 18px; text-anchor: middle; font-family: serif;">
<circle
id="myCircle"
cx="100" cy="75" r="50"
stroke="firebrick"
stroke-width="3" />
<text x="100" y="155">Hello World</text>
<text x="100" y="175">From An SVG File!</text>
</g>
</svg>
First, notice that we are specifying a width and height on our SVG file as well on the <svg>
root tag, as well as providing a background color for the entire SVG file. If you leave off a background color we default to making it transparent, which can be useful if you want to have other content on your HTML page show through.
Next, notice the g
element, which is a grouping element. You can think of this element as exactly akin to Photoshop's grouping operation. Grouping things together can make it easy to manipulate them all at once when scripting or transforming elements. In addition, you can provide default values for certain styles that will propagate to all the children. In the example above, we provide a default fill value with fill="blue"
that all children will inherit, as well as default text values using a style=""
attribute that all children will inherit: setting the font size to 18 pixels; centering the text in the middle of the image; and making the font be a serif font.
We then use a circle
element to draw a circle on the screen. We specify the center of where to place the circle on the page using cx
and cy
, and then specify a radius using r
. We can specify the line color to use on the outside using the stroke
attribute, and give the width of the line using stroke-width
.
In SVG, text doesn't line wrap, so we provide two text
elements and give the x
and y
location to place them at.
By default we use the Flash based renderer on Internet Explorer while using the native SVG support on other browsers like Firefox and Safari. You can optionally override this to force the Flash renderer on all browsers. This can make development easier, since you can use the SVG Web Flash based renderer on Firefox plus its great set of debugging and development tools; you can also choose to deploy using the Flash based renderer for all browsers in order to gain SVG features that might not be natively present or to have a more consistent deployment environment.
You can change the renderer in two ways. First, you can force the Flash renderer by changing the URL of your page with the following flag:
http://127.0.0.1:8080/samples/javascript-samples/helloworld.html?svg.render.forceflash=true
Clicking the link above, for example, will show the helloworld.html sample but will force the Flash renderer to be used for everything. You can also set svg.render.forceflash
to false
.
The second way to override the renderer used is by adding a META
tag into your HTML page:
<meta name="svg.render.forceflash" content="true">
Let's look at how you can deploy your SVG files and SVG Web to your web server.
First, upload the ZIP archive to your web server. The following files are required to be present:
- src/svg.js
- src/svg.htc
- src/svg.swf
The other files in the ZIP are optional; some are utilities that can help with deployment.
Note that all of the SVG Web files by default must be on the same domain as any web pages that might use the library. For example, if you have http://example.com/mypage.html
, then you should ensure the files above are also on http://example.com
. Putting them on a static.example.com
would not work. This arises from limitations in Flash and the Microsoft HTC (svg.htc
) file that are used by SVG Web. SVG Web has partial support for hosting many of its files on a different domain however; see the User Manual for details.
You must ensure that your web server has the correct MIME settings for Flash SWF files (application/x-shockwave-flash
), Microsoft HTC files (text/x-component
), and SVG files (image/svg+xml
). Since many developers don't know what MIME types are or don't have the ability to change this setting on their web server, SVG Web comes with a number of utilities to make this easier.
First, your web server might already be configured out of the box and there is nothing to change. To test this, make sure the file src/tools/config.html
is on your web server and hit it with a web browser. This file will scan and make sure the MIME type settings are set. If they are not it will report this to you and you will have to move to the next step. If the SVG mime type is not set correctly you can generally get away without changing this; note though that Firefox can sometimes exhibit bugs if the SVG MIME type is not set to image/svg+xml
.
At this point the best step is to actually change your web server to add these MIME types. If you don't have the ability or background to add MIME types to your web server, three easy files have been provided that will do the work for you based on what you can run on your server (PHP, JSP, or ASP). Based on what you can run on your server, choose one of the following files:
src/svg-htc.php
- Will do the MIME work for you if you can run
PHP on your web server.src/svg-htc.jsp
- Will do the MIME work for you if you can run
JSP on your web server.src/svg-htc.asp
- Will do the MIME work for you if you can run
ASP on your web server.If you choose one of these, you must indicate so using the optional
data-htc-filename
attribute in any HTML page that uses SVG Web:
<script src="../svg.js" data-path=".." data-htc-filename="svg-htc.php"></script>
Only give the filename, such as svg-htc.jsp
, rather than a full
path, such as ../../svg-htc.jsp
. Note that if you use
one of these files in order to automatically force the MIME type, when you run
any of the bundled demos or samples you will have to append the following
query string to tell them to use your different HTC file or else they will not work:
http://example.com/svgweb/samples/demo.html?svg.htcFilename=svg-htc.php
Let's take a look at scripting your SVG using JavaScript. This section is not meant to be a tutorial on JavaScript plus SVG; rather, it is a very basic overview including some small divergences necessary for SVG Web.
SVG Web includes a large set of the DOM (Document Object Model) when working with SVG. It is fairly complete though there are some omissions or areas which are still being worked on. Your JavaScript, even on Internet Explorer, has the 'illusion' of native SVG support.
Let's start with scripting SVG that is embedded right into a web page. We will be using the source in helloworld.html
. First, before working with the DOM or SVG on your page you must wait for SVG Web to finish loading:
window.onsvgload = function() {
// do stuff now
}
Notice that we use window.onsvgload
rather than window.onload
. You can alternatively also use window.addEventListener
with the SVGLoad
event (this also works on Internet Explorer):
window.addEventListener('SVGLoad', function() {
// function to be called when SVG Web and the page is done loading
}, false)
On the helloworld.html
page you will see two buttons, "Change Colors" and "Change Text." When clicked, they change the color of the circles in both SVG images, as well as change the text. The script for all of this is just a normal <script>
tag embedded into the page, in the two functions changeColors
and changeText
. Let's look at the changeColors
method:
function changeColors() {
// get elements from our embedded SVG first
// use getElementById
var circle = document.getElementById('myCircle');
// change using setAttribute
circle.setAttribute('stroke', 'green');
// can also use style property
circle.style.fill = '#8A2BE2';
// change the value inside our SVG OBJECT now
// use the 'contentDocument' property to navigate into the SVG OBJECT
var doc = document.getElementById('mySVGObject').contentDocument;
circle = doc.getElementById('myCircle');
circle.style.fill = '#8A2BE2';
}
First, you will see that we get our circle from the page using a normal document.getElementById('myCircle')
call. This will grab the circle
that was directly embedded into the page. Once we have our circle, we can change the color either by using a setAttribute
call or by simply changing the circle.style.fill
value; either cause the same results. Note that all of this code works even on Internet Explorer; SVG Web does the necessary magic to give the illusion of native support.
In order to change the color of the circle inside our SVG OBJECT (the second SVG image), we have to 'navigate' into it. The key here is to use the contentDocument
property. We first fetch the SVG OBJECT from the page by ID, and then grab the contentDocument
property. At this point we have a normal document
object we can now work with, so we simply grab the circle that is embedded inside this SVG object and change its color as well:
// use the 'contentDocument' property to navigate into the SVG OBJECT
var doc = document.getElementById('mySVGObject').contentDocument;
circle = doc.getElementById('myCircle');
circle.style.fill = '#8A2BE2';
Next, let's look at the changeText
function; we've written it a bit differently than necessary to show you some other DOM functions that can be used:
function changeText() {
// use getElementsByTagNameNS to get our text from our embedded SVG
// 'svgns' is a 'magic' variable that we make available; it is just
// the SVG namespace 'http://www.w3.org/2000/svg' so you don't always
// have to remember it. We also make the variable 'xlinkns' available.
var textElems = document.getElementsByTagNameNS(svgns, 'text');
// change the text Hello World to Goodbye World
for (var i = 0; i < textElems.length; i++) {
if (textElems[i].childNodes[0].nodeValue == 'Hello World') {
textElems[i].childNodes[0].nodeValue = 'Goodbye World';
}
}
// change the text inside our SVG OBJECT as well
var doc = document.getElementById('mySVGObject').contentDocument;
textElems = doc.getElementsByTagNameNS(svgns, 'text');
for (var i = 0; i < textElems.length; i++) {
if (textElems[i].childNodes[0].nodeValue == 'Hello World') {
textElems[i].childNodes[0].nodeValue = 'Goodbye World';
}
}
}
First, notice that we can get SVG tags from the page by tag name not just by ID; however, it is very important that you use the namespace-aware method getElementsByTagNameNS
instead of getElementsByTagName
or else things won't work! You will also notice that we access the global variable svgns
that SVG Web makes available to easily work with the SVG namespace (a similar one is available for the XLink namespace, xlinkns
, when doing hyperlink code). These combine together to make it easy to work with the namespace-aware functions:
var textElems = document.getElementsByTagNameNS(svgns, 'text');
This will grab all of the SVG text
elements that are directly embedded in the page (i.e. it will return two text
elements); it will not return anything from SVG OBJECTs, since those are not directly in the page. Once we have our elements, we loop over them and get their text values by calling textElems[i].childNodes[0].nodeValue
. The value of an SVG text
is held as a DOM Text Node, so we have to grab the first child and get its value. Once we find any nodes that have the value "Hello World" we then change the text value in a similar manner.
We don't dynamically create any nodes in our helloworld.html
sample, but here is a simple example code block showing how we would do this. Most importantly, notice how we use the namespace aware createElementNS
method instead of createElement
:
var el = document.createElementNS(svgns, 'circle');
el.setAttribute('cx', 200);
el.setAttribute('cy', 200);
el.setAttribute('r', 5);
el.setAttribute('fill', '#223FA3');
el.setAttribute('stroke-width', '1px');
el.setAttribute('stroke', 'black');
var group = document.getElementById('myGroup');
group.appendChild(el);
One small important thing to keep in mind is when you create DOM text nodes that you are going to use with your SVG, you must add an extra boolean argument to help SVG Web out:
var textNode = document.createTextNode('hello world', true);
var svgText = document.createElementNS(svgns, 'text');
svgText.setAttribute('x', 100);
svgText.setAttribute('y', 100);
svgText.appendChild(textNode);
Now let's take a look at doing scripting inside of an SVG file rather than directly embedding into an HTML page. We will use the helloworld.svg
file as our sample. I'll show you the full code sample first and then break it apart:
<svg onload="loaded()">
<script type="text/javascript"><![CDATA[
function loaded() {
// change onloadFunc to point to your real onload function that you
// want called when the page is truly ready
var onloadFunc = doload;
if (top.svgweb) {
top.svgweb.addOnLoad(onloadFunc, true, window);
} else {
onloadFunc();
}
}
function doload() {
// developers original onload handler
// add an event listener to our circle; on* style events added right
// to the markup are not yet supported
var circle = document.getElementById('myCircle');
circle.addEventListener('mousedown', function() {
alert('You pressed the mouse button on our circle!');
}, false);
}
]]></script>
First, notice that we have to do a little bit of trickery around the onload
event in order to help SVG Web. If you want to have any script inside your SVG file, you must change the onload
attribute to point to a special function, loaded
that you should simple cut and paste into your code and change the onloadFunc
variable to point to the name of your real function:
function loaded() {
// change onloadFunc to point to your real onload function that you
// want called when the page is truly ready
var onloadFunc = doload;
if (top.svgweb) {
top.svgweb.addOnLoad(onloadFunc, true, window);
} else {
onloadFunc();
}
}
For SVG events, we only currently support the addEventListener
method:
// add an event listener to our circle; on* style events added right
// to the markup are not yet supported
var circle = document.getElementById('myCircle');
circle.addEventListener('mousedown', function(evt) {
alert('You pressed the mouse button on our circle: ' + evt.target.id);
}, false);
This will cause an alert box to appear when a user presses the mouse button down. Notice that the event
object is passed into the method (even on Internet Explorer -- use this instead of window.event
). You can use the event
object to get information, such as the id of the target: evt.target.id
.
This section provides some tips and tricks to help with performance and reliability.
If you are doing a bunch of DOM operations in a loop, such as creating elements or updating an attribute, you can significantly speed things up by using the suspendRedraw
methods. An example:
var root = document.getElementsByTagNameNS(svgns, 'svg')[0];
var circles = document.getElementsByTagNameNS(svgns, 'circle');
var suspendID = root.suspendRedraw(5000);
// let's say there are 500 circles
for (var i = 0; i < circles.length; i++) {
circles[i].setAttribute('fill', 'red');
}
root.unsuspendRedraw(suspendID);
// could also do root.unsuspendRedrawAll() to clear out all suspended
// operations
The suspendRedraw method takes a timeout in milliseconds until redrawing is forced; higher numbers are recommended. See the suspendRedraw section in the User Manual for more details on these methods.
If you are creating many DOM nodes at once, you should use the DOM DocumentFragment API. This will significantly speed things up, especially if you are creating these nodes on page load. To create a DocumentFragment for use with SVG, you should call document.createDocumentFragment(true)
. Note the extra true
parameter -- this is required by SVG Web to help us know that this DocumentFragment will be used with SVG, possibly going into our fake Flash backend. A small code example:
// note the extra 'true' argument
var frag = document.createDocumentFragment(true);
for (var i = 0; i < 100; i++) {
var circle = document.createElementNS(svgns, 'circle');
circle.setAttribute('x', i * 10);
circle.setAttribute('y', 10);
circle.setAttribute('r', 5);
circle.setAttribute('fill', 'red');
// append to DocumentFragment
frag.appendChild(circle);
}
// now append the DocumentFragment to the DOM
var svg = document.getElementsByTagNameNS(svgns, 'svg')[0];
svg.appendChild(frag); // DocumentFragment disappears leaving circles
See the section on DocumentFragments in the UserManual for more details.