SVG has had a long and strange journey to the world of ‘emerging technologies” SVG was actually defined in 1999, so it’s not exactly the new kid on the block. Still, it took a while to catch on, so in some ways it feels like the new kid on the block. Like Canvas, SVG allows developer sot create graphics in the browser using native web technologies. Unlike Canvas SVG is a vector based grammar and, since it’s defined as XML it also allows for access using common DOM manipulation tools. One of the most difficult issues when dealing with Canvas is the need to manually manage the state, properties and events of individual elements. Since SVG elements are simple DOM elements, properties are stored as part of the regular DOM and access to individual elements is available using traditional DOM access methods like document.geElementById
and document.getElementsByTagName
.
One driver of popularity for SVG has been the emergence the RaphaelJS library. Raphael provides a convenient API on top of the specification and provides some measure of support for legacy IE browsers by rendering the output of Rapehl instructions as Vector Markup Language (VML.)
The following example shows Raphael and SVG in action. Example output can be seen in the following figure.
The following code sample illustrates using Raphael to draw 10 random circles on an SVG element, filling them with a random gradient fill. The code is quite simple, with a new paper
variable containing the instance of Raphael in use and then straightforward methods circle()
and attr()
used to create circles and fill them with the fancy gradient fill.
<!DOCTYPE html> <html> <head> <meta charset=UTF-8"> <title>SVG</title> </head> <style type='text/css'> #svg { width:100%; height:600px; } </style> </head> <body> <div id="svg"></div> <script src='https://cdnjs.cloudflare.com/ajax/libs/raphael/2.1.0/raphael-min.js'></script> <script src='demo.js'></script> </body> </html>
window.onload=function(){ var svg = document.getElementById("svg"), paper = Raphael( svg ), circle, width = svg.offsetWidth, height = svg.offsetHeight; for (var i = 0; i < 10; i++) { circle = paper.circle( parseInt(Math.random() * width), parseInt(Math.random() * height ), parseInt(Math.random() * 200)); circle.attr({ "fill": "r" + hex() + "-" + hex(), "fill-opacity": "0.5", "stroke": "none" }); circle.click(function() { console.log(this); this.animate({ cx: parseInt(Math.random() * width), cy: parseInt(Math.random() * height), r: parseInt(Math.random() * 200) }, 1000, "bounce") }); } function hex() { //http://paulirish.com/2009/random-hex-color-code-snippets/ return '#' + Math.floor(Math.random() * 16777215).toString(16); } }
Inspecting the output the underlying markup isn’t quite so succinct, although it should be readable if you’re familiar with XML syntax and can follow along with the code that generated the example. The following code sample shows a single circle marked up using SVG syntax.
The interesting pieces to note are the definition of the radialGradient
in the defs
element. defs
are used for reusable content. You can see it referred to in the circle element’s fill url.
<svg height="400" version="1.1" width="400" xmlns="http://www.w3.org/2000/svg" style="overflow: hidden; position: absolute; left: 0px; top: 0px;"> <desc>Created with Raphaël 2.1.0</desc> <defs> <radialGradient id="0r_7d7f2f-_bbb372" fx="0.5" fy="0.5"> <stop offset="0%" stop-color="#7d7f2f"/> <stop offset="100%" stop-color="#bbb372" stop-opacity="0.5"/> </radialGradient> </defs> <circle cx="170" cy="68" r="61" fill="url(#0r_7d7f2f-_bbb372)" stroke="none" style="opacity: 1; fill-opacity: 1;" opacity="1" fill-opacity="1"/> </svg>