08. Introducing SVG

The Scalable Vector Graphics (SVG) language is one of the best-known XML applications. It is a W3C specification taht provides markup elements to describe two-dimensional graphics. The Mozilla-based Firefox and Opera web browsers provide native support for the SVG Full specification and many cellphones support a subset of the Full version - SVG Tiny or SVG Basic.

SVG offers significant advantages over other graphic formats:

The SVG standard has been explicitly designed to work well with other established technologies, such as CSS and JavaScript. This means that stylesheets can be used to control the appearance of SVG elements and scripts can provide functionality.

Where traditional graphic formats, such as GIF and PNG, are stored in machine-readable binary code SVG is text-based - so each part of the graphic is human -readable and can be readily edited in any plain text editor, like Notepad. Additionally, they can be read by search engines - so they may be indexed according to their content.

All vector formats describe graphics as a series of shapes, drawn from point to point. For instance, a rectangular vector shape is defined by the coordinates of each corner point. This efficient method differs from that employed by bitmap formats, which laboriously describe the color of each pixel. Consequently SVG graphics can be smaller in file-size for large graphics. Most importantly, vector graphics can be scaled up without any loss in quality whatsoever. This means that, unlike a bitmap graphic, an SVG graphic can be displayed equally well on a handheld device, in small-scale, and on a desktop device in a larger scale - a significant advantage, given teh proliferation of handheld devices.

Producing graphic shapes

The SVG specification provides <rect>, <circle>, and <ellipse> tags to draw simple shapes. These have x and y attributes to determine the position, width and height attributes to determine the size,and a fill attribute to determine the color of the shape.

More complex shapes can be drawn by specifying a list of x, y coordinates to the points attribute of the <polygon> tag.

All the shape tags support further optional attributes to specify opacity , border width (stroke-width) and color (stroke) .

Lets create an SVG document that draws a selection of shapes:

<?xml version="1.0" encoding="UTF-8" ?>
<!-- add teh SVG root element stating the version and feature set, namespace, and overall size -->
<svg version="1.1" baseProfile="full"
xmlns="http://www.w3.org/2000/svg"
width="500px" height="250px">

<title>SVG Shapes</title>
<!-- Draw a simple red rectangle. -->
<rect x="10" y="10" width="100px" height="100px" fill="red" />
<!-- Draw a red rectangle with rounded corners. -->
<rect x="120" y="10" rx="20" ry="20" width="100px" height="100px" fill="red" />
<!-- Draw a red rectangle with quarter opacity. -->
<rect x="230" y="10" width="100px" height="100px" fill="red" opacity = "0.25"/>
<!-- Draw a yellow rectangle with red 3px border. -->
<rect x="340" y="10" width="100px" height="100px" fill="yellow" stroke = "red" stroke-width = "3px"/>
<!-- Draw a simple blue circle. -->
<circle fill="blue" cx="60" cy="170" r="50px" />
<!-- Draw an orange ellipse at cx,cy with radii rx,ry. -->
<ellipse cx="170" cy="170" rx="50px" ry="30px" fill="orange" />
<!-- Draw a simple lime green triangle.-->
<polygon fill="lime" points="230,220 280,120 330,220" />
<!-- Draw a purple pentagon with half opacity. -->
<polygon fill="purple" points="360,220 340,158 392.5,120 445,158 425,220" />
</svg>

Producing graphic lines

The SVG specification provides a <line> tag to draw lines. This has x1 and y1 attributes to determine where the line will start, and similar x2, y2 attributes to determine where it will end. Line color is specified by the stroke attribute, as lines have no fill property, and thickness is specified by the stroke-width attribute. Dashed lines can be created by adding a stroke-dash-array attribute to specify the dash length and interval.

All lines are simply slender rectangles by another guise - a <rect> element can therefore be used to create a "line" and may be filled by any color of gradient fill.

For instance:

<?xml version="1.0" encoding="UTF-8" ?>
<svg version="1.1" baseProfile="full"
xmlns="http://www.w3.org/2000/svg"
width="400px" height="200px">
<title>SVG Lines</title>
<!-- Draw a simple red horizontal line. -->
<line x1="10" y1="10" x2="400" y2="10" stroke="red" stroke-width="5px" />
<!-- Draw a simple blue vertical line. -->
<line x1="10" y1="10" x2="10" y2="200" stroke="blue" stroke-width="5px" />
<!-- Draw a simple angled green line. -->
<line x1="10" y1="10" x2="400" y2="100" stroke="green" stroke-width="5px" />
<!-- Draw a dashed orange line. -->
<line x1="10" y1="120" x2="400" y2="120" stroke="orange" stroke-width="5px" stroke-dasharray="10,2" />
<!-- Draw a fancy dashed lime green line. -->
<line x1="10" y1="150" x2="400" y2="150" stroke="lime" stroke-width="20px" stroke-dasharray="10,2,10" />
<!-- Create a definitions block. -->
<defs>
<!-- Define a linear gradient. -->
<linearGradient id = "LG1">
<!-- Start at yellow and finish at purple. -->
<stop offset = "0%" stop-color = "yellow" />
<stop offset = "100%" stop-color = "purple" />
</linearGradient>
</defs>

<!-- Draw a rect (line) filled with a linearGradient fill. -->
<rect x="10" y="180" width="390px" height ="20px" fill ="url(#LG1)" />
</svg>

Producing graphic paths

Lines can be made to follow a particular "path" by specifying a list of x, y coordinates to the points attribute in a <polyline> tag. This works much like the <polygon> element, which is used to draw shapes, but its appearance is determined by stroke, not fill.

The <path> element is the most important SVG element as it can draw both straight and curved lines along a specified path, and supports both fill and stroke values so it can draw complex shapes. Its d (data) attribute specifies the path as s series of x and y coordinates in a list separated by white space - not commas. The path list also includes commands, like those in the table below:

Command Data Description
M x y moveTo
- move the pen to x y but draw no line. All path data must begin with a moveTo command
L x y lineTo
- draw a line from the current point to x y
H x horizontal lineTo
- draw a horizontal line from the currnt point to X
V y vertical lineTo
- draw a vertical line from the current point to y
Q x1 y1
x y
quadratic bezier curveTo
- draw a curved line from the current point to x y, using control point x1 y1 to calculate the curve
Z - closePath
- draw a line from the final point to the first point

For instance:

<?xml version="1.0" encoding="UTF-8" ?>
<svg version="1.1" baseProfile="full"
xmlns="http://www.w3.org/2000/svg"
width="400px" height="300px" >
<title>SVG Paths</title>
<!-- Lines. -->
<polyline stroke="red" stroke-width="3px" fill = "none" points="10,10 300,10 300,80 400,100" />
<path stroke="green" stroke-width="3px" fill = "none" d = "M 10 20 L 290 20 290 90 400 110" />
<path stroke="blue" stroke-width="3px" fill = "none" d = "M 10 30 H 280 V 100 L 400 120" />

<!-- Curves. -->
<path stroke="purple" stroke-width="3px" fill = "none" d = "M 10 50 Q 100 90 10 130" />
<path stroke="purple" stroke-width="3px" fill = "lime" d = "M 90 50 Q 180 90 90 130" />

<path stroke="purple" stroke-width="3px" fill = "none" d = "M 170 50 Q 260 90 170 130 Z" />
<!-- Combined lines and curves. -->
<path stroke="orange" stroke-width="3px" stroke-dasharray = "10,2" fill = "none" d = "M 10 150 H 160 Q 210 220 260 150 H 400" />
</svg>

Transforming graphic groups

SVG documents can be structured to group a number of shapes within a <g></g> element. Values assigned to presentational attributes within a <g> tag are inherited by its child elements, so common values need not be assigned in each child element. For instance, with a parent element of <g fill="red"> each child element will inherit the fill value to be colored red.

A value inherited from a parent element can, however, be overridden by assigning a different value to that attribute in teh child tag. So that <rect fill="blue"> would override an inherited red fill color to ensure that child is colored blue.

The appearance of any SVG element can be adjusted using the transform attribute to specify a transformation function to scale, skew, rotate, or translate its properties. Where this is assigned to a <g> element the transformation is applied to the entire group.

For instance:

<?xml version= "1.0" encoding = "UTF-8" ?>
<svg version="1.1" baseProfile="full"
xmlns="http://www.w3.org/2000/svg"
width = "400px" height = "300px" >
<title>SVG Transforms</title>
<!-- scale, translate, skew, rotate. -->
<g font-size = "16pt" font-family = "Arial">
<rect x = "10" y= "10" width = "55px" height = "25px" fill = "red"/>
<rect x = "65" y= "10" width = "120px" height = "25px" fill = "yellow"/>
<text x = "15" y = "30" fill = "white" >SVG</text>
<text x = "70" y = "30" fill = "black">Logo</text>
</g>
<g font-size = "16pt" font-family = "Arial" transform = "translate(190,0)">
<rect x = "10" y= "10" width = "55px" height = "25px" fill = "red"/>
<rect x = "65" y= "10" width = "120px" height = "25px" fill = "yellow"/>
<text x = "15" y = "30" fill = "white" >SVG</text>
<text x = "70" y = "30" fill = "black">Translated</text>
</g>
<g font-size = "16pt" font-family = "Arial" transform = "translate(0,30), skewY(20)">
<rect x = "10" y= "10" width = "55px" height = "25px" fill = "red"/>
<rect x = "65" y= "10" width = "120px" height = "25px" fill = "yellow"/>
<text x = "15" y = "30" fill = "white" >SVG</text>
<text x = "70" y = "30" fill = "black">Y Skewed</text>
</g>
<g font-size = "16pt" font-family = "Arial" transform = "translate(200,50),rotate(20)">
<rect x = "10" y= "10" width = "55px" height = "25px" fill = "red"/>
<rect x = "65" y= "10" width = "120px" height = "25px" fill = "yellow"/>
<text x = "15" y = "30" fill = "white" >SVG</text>
<text x = "70" y = "30" fill = "black">Rotated</text>
</g>
<g font-size = "16pt" font-family = "Arial" transform = "translate(0,130), scale(2)">
<rect x = "10" y= "10" width = "55px" height = "25px" fill = "red"/>
<rect x = "65" y= "10" width = "120px" height = "25px" fill = "yellow"/>
<text x = "15" y = "30" fill = "white" >SVG</text>
<text x = "70" y = "30" fill = "black">Scaled</text>
</g>
</svg>

Adding hyperlinks in SVG

Note: Links will only work if the XLink namesapce has been included in the root element and its prefix is included with the href attribute

The SVG specification does not provide native support for hyperlinking, but this can be provided by the XLink language. Incorporating XLink into an SVG document is simply a matter of including its namespace in the root <svg> element.

XLink supports the href attribute of an <a> anchor element that can specify a link target, just like in HTML, but with XLink the namespace prefix must be included - usually as xlink:href

Adding XLink support to an SVG document also enables other types of link to be made using the xlink:href attributes:

Copying multiple instances of a defined group with a <use> element is easier, and more efficient, than repeating all the elements for each instance.

For instance:

<?xml version="1.0" encoding="UTF-8" ?>
<svg version="1.1" baseProfile="full"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="400px" height="300px" >
<title>SVG Links</title>
<!-- Defining a group. -->
<defs>
<g id = "exclaim" font-size = "48pt" >
<circle r="30px" fill = "red" />
<text x = "-10" y = "20" fill = "white" >!</text>
</g>
</defs>

<!-- Using xlink:href. -->
<!-- 1. Create a hyperlink. -->
<a xlink:href="http://www.auxy.com/study/" target="_blank">
<text x = "10" y = "150">Follow this link to discover more</text>
</a>
<!-- 2. Link to a script. -->
<script type="text/javascript" xlink:href = "script.js" />
<!-- 3. Reference a Path -->
<path id = "fun-path" d="M40,120 Q50,-20 390,80" fill = "none" stroke = "none"/>
<text fill = "red" font-size = "30pt" >
<textPath xlink:href="#fun-path">Having Fun with SVG</textPath>
</text>
<!-- 4. Use a defined group. -->
<use x="100" y="100" xlink:href = "#exclaim" />
<use x="200" y="100" xlink:href = "#exclaim" />
<use x="300" y="100" xlink:href = "#exclaim" />
</svg>

Scripting for graphic events

SVG graphics recognize events created by user actions and can be made to respond to those events by scriptiong event-handler functions in JavaScript. Typically these will respond to mouse actions that create mouseover, mousedown, mouseup, and mouseout events when teh user interacts with the graphic - generally known as a "rollover" effect.

<?xml version="1.0" encoding="UTF-8" ?>
<svg version="1.1" baseProfile="full"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink = "http://www.w3.org/1999/xlink"
width="103" height="93" >
<title>SVG Events</title>
<script type="text/javascript" xlink:href = "events.js" />
<!-- Background color shape. -->
<polygon points = "2,30 50,30 50,2 101,45 50,91 50,60 2,60" fill = "yellow" stroke = "none" />
<!-- Button text. -->
<g font-size = "13pt" font-weight="bold">
<text x="11" y="51" fill = "black">Button</text>
<text x="10" y="50" fill = "white">Button</text>
</g>
<!-- Interactive shape. -->
<polygon points = "2,30 50,30 50,2 101,45 50,91 50,60 2,60"
fill-opacity="0.0" stroke = "none" stroke-width = "4px"
onmouseover = "setBtn(this,1)" onmousedown = "setBtn(this,2)"
onmouseup = "setBtn(this,3)" onmouseout = "setBtn(this,4)"
onclick = "alert('Button Clicked')"
/>
</svg>

Filename: event.js

// Button click event-handler.
function setBtn(obj,state)
{
if(state == 1) obj.setAttribute("stroke","red");
else if(state == 2) obj.setAttribute("stroke","green");
else if(state == 3) obj.setAttribute("stroke","blue");
else if(state == 4) obj.setAttribute("stroke","none");
}

Click here for an example

Embedding SVG in HTML

SVG images can easily be scaled to any dimension, without loss of quality, in preparation for embedding into a web page. The width and height attributes of the root <svg> element determine its size. The image can be made to appear scaled down, however, by adding a viewBox attribute, to define the viewable area, then reducing the width and height values to the desired scale. A viewBox attribute describes the x,y coordinates of the top-left and bottom-right corners of the viewable area. For instance, viewBox="0,0 400,300" describes a viewable area that is 400 pixels wide and 300 pixels high. This area could be scaled down to 50% by specifying width = "200px" and height ="150px" .

Once scaled to the desired size the SVG image can be embedded into the HTML document using the <object> tag, which specifies the same dimensions as the width and height attributes of the <svg> root element. The <object> tag also specifies the SVG type as "image/svg+xml" and assigns its URL to a data attribute. It's good practice to also have the <object> element provide alternative content for browsers that do not support SVG.

For instance:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>SVG in HTML</title>
<meta http-equiv = "Content-Type" content = "text/html;charset=UTF-8" />
<script type = "text/javascript" src = "embed.js"></script>
</head>
<body>
<object type = "image/svg+xml" width = "95px" height = "50px" data = "usflag.svg">
<a href = "javascript:info('en','parent')">English</a>&nbsp;&nbsp;&nbsp;&nbsp;
</object>
<object type = "image/svg+xml" width = "95px" height = "50px" data = "spflag.svg">
&nbsp;<a href = "javascript:info('sp','parent')">Spanish</a>
</object>

<div id = "box" style="position:absolute;top:5px;left:210px">
Please select your language.<hr/>
Seleccione por favor su lengua.</div>
</body>
</html>

Filename: spflag.svg

<?xml version="1.0" encoding="UTF-8"?>
<svg version ="1.1" baseProfile = "full"
xmlns ="http://www.w3.org/2000/svg"
xmlns:xlink = "http://www.w3.org/1999/xlink"
width="95" height="50" viewBox="0,0 247,130">
<script type = "text/javascript" xlink:href ="embed.js" />
<g onclick = "info('sp','child')" onmouseover = "this.style.cursor='pointer'">
<rect x = "0" y = "0" width="247" height="33" fill="#ED2024" />
<rect x = "0" y = "97" width="247" height="33" fill="#ED2024" />
<rect x = "0" y = "33" width="247" height="64" fill="#F8ED37" />
</g>
</svg>

Filename: embed.js

function info(lang,doc) {
try {
// Default assumes call emanates from the HTML parent document.
var box = document.getElementById("box");
// But if the call emanates from a child SVG document...
if(doc == "child") {
// Prefix the parent DOM object to address the <div>.
box = parent.document.getElementById("box")
}
// Write the message in the chosen language.
if(lang == "en") {
box.innerHTML = "Hello!<hr>Here is the information in English...";
}else if(lang == "sp"){
box.innerHTML = "Hola!<hr>Aqu&iacute; est&aacute; la informaci&oacute;n en Espa&ntilde;ol...";
}
}
catch(error) {
// Or surrender.
alert(error.description);
} }