A jQuery plugin that lets you interact with an SVG canvas.
The current version is 1.4.5 and is available under the MIT licence. For more detail see the documentation reference page, or the graphing reference or plotting reference pages. Or see a minimal page that you could use as a basis for your own investigations.
SVG (Scalable Vector Graphics) is a modularized language
for describing two-dimensional vector and mixed vector/raster
graphics in XML
. It is a
W3C Recommendation
currently at version 1.1.
SVG is a language for describing two-dimensional graphics in XML. SVG allows for three types of graphic objects: vector graphic shapes (e.g., paths consisting of straight lines and curves), images and text. Graphical objects can be grouped, styled, transformed and composited into previously rendered objects. The feature set includes nested transformations, clipping paths, alpha masks, filter effects and template objects.
SVG is implemented in Firefox natively from version 1.5, Opera natively from version 8.5, Safari natively from version 3.0, and in IE from Windows 98 onwards via the Adobe SVG viewer or the Renesis Player. Not every SVG construct is supported by these implementations.
This plugin allows you to manipulate the SVG from JavaScript. For more details see the reference documentation, or the graphing reference or plotting reference pages.
Download and include the jQuery SVG CSS and JavaScript in the head section of your page.
<link rel="stylesheet" type="text/css" href="css/jquery.svg.css">
<script type="text/javascript" src="js/jquery.svg.js"></script>
Alternatively, you can use the packed or minified versions of the code:
jquery.svg.pack.js (15.1K vs 56.7K) or
jquery.svg.min.js (19.6K, 6.1K when zipped).
Attach an SVG canvas to a <div>.
$('#svgintro').svg({onLoad: drawIntro});
Then respond to the load completion and start working with it.
function drawIntro(svg) {
svg.circle(75, 75, 50,
{fill: 'none', stroke: 'red', strokeWidth: 3});
var g = svg.group({stroke: 'black', strokeWidth: 2});
svg.line(g, 15, 75, 135, 75);
svg.line(g, 75, 15, 75, 135);
}
You can remove the SVG functionality if you no longer need it.
$('#remove').toggle(function() {
$(this).text('Re-attach');
$('#svgintro').svg('destroy');
},
function() {
$(this).text('Remove');
$('#svgintro').svg({onLoad: drawIntro});
});
For IE, a blank SVG document is initially loaded that registers itself with
the plugin and allows access to its internal structure. This is the
blank.svg document. Because of this requirement, you must wait
for the document to be loaded before accessing the SVG instance and using it.
Use the onLoad setting to be notified when loading is complete.
The callback is not necessary for the other browsers, but its use provides
a consistent access pattern for them all.
Processed divisions are marked with a class of hasSVG
and are not re-processed if targetted a second time.
As well as the basic SVG functionality, the plugin allows for extending its
abilities via additional packages. In this way you can avoid loading code
that you are not going to use. Most extensions add an entry point object to
the SVG manager object, returned by $(selector).svg('get'),
from which you can access its functionality.
Currently the following extensions are available:
| Package | Entry point | Functionality |
|---|---|---|
| jquery.svganim.js | - | Support for jQuery animation of SVG attributes. Since 1.1.0. |
| jquery.svgdom.js | - | Support for jQuery/SVG DOM compatibility. Since 1.4.0. |
| jquery.svgfilter.js | svg.filter | Support for SVG filter element and filter definitions. |
| jquery.svggraph.js | svg.graph | Support for basic graphing using SVG. |
| jquery.svgplot.js | svg.plot | Support for plotting functions using SVG. Since 1.3.0. |
To use these extensions just load them after the main jQuery SVG Javascript in the head section of your page.
<script type="text/javascript" src="jquery.svg.js"></script>
<script type="text/javascript" src="jquery.svggraph.js"></script>
Each extension registers itself with the SVG framework as shown, indicating the name of its entry point and the class (function) that encapsulates its functionality:
$.svg.addExtension('graph', SVGGraph);
Attach an SVG canvas and retrieve the SVG instance as before. Then access the new functionality through its entry point:
$('div selector').svg();
var svg = $('div selector').svg('get');
svg.graph.addSeries('Firefox', [0.00, 4.06, 8.13, 9.95],
'lightgreen', 'green', 3);
These examples are taken from the SVG 1.1 specification to show how they might be implemented using this package.
Select one of the examples taken from the SVG specification that demonstrates how the functionality might be produced using this package. Both the original SVG document and the jQuery SVG code are shown below.
The SVG component may be updated with inline SVG elements, be cleared of all content,
or be loaded with external SVG documents. In the latter case, you may pass additional
settings to add to any existing content (addTo: true) or automatically
clear it first (addTo: false - the default).
You can also specify a callback function (onLoad: loadDone) to
be notified when the external document (loaded asynchronously) has completed.
The function receives the current SVG wrapper object as a parameter,
and an additional message parameter if there was an error.
The this object is the SVG container division.
<svg:svg id="svginline">
<svg:g>
<svg:rect width="350" height="50" x="20" y="90" fill="blue"></svg:rect>
<svg:text x="40" y="120" fill="white" font-weight="bold">
This came from an inline SVG fragment</svg:text>
</svg:g>
</svg:svg>
$('#svgload').svg();
$('#addInline').click(function() {
var svg = $('#svgload').svg('get');
svg.add($('#svginline > *'));
resetSize(svg);
});
$('#clear1').click(function() {
$('#svgload').svg('get').clear();
});
$('#loadExternal').click(function() {
var svg = $('#svgload').svg('get');
svg.load($('#loadURL').val(), {addTo: $('#addTo')[0].checked,
changeSize: false, onLoad: loadDone});
resetSize(svg);
});
/* Callback after loading external document */
function loadDone(svg, error) {
svg.text(10, 20, error || 'Loaded into ' + this.id);
}
By adding the jquery.svganim.js extension
to your page you can easily animate several of the attributes of the
various SVG elements using the standard jQuery
animate function.
All attributes must be prefixed by 'svg' to identify them as SVG settings
and are written in camelCase, e.g. svgStrokeWidth.
Many of the values may be expressed as exact pixels or as percentages.
You can also use the '+=' or '-=' prefixes for relative values.
var myrect = svg.rect(25, 25, 150, '25%', 10, 10,
{fill: 'none', stroke: 'blue', strokeWidth: 3,
transform: 'rotate(0, 100, 75)'});
$(myrect).animate({svgWidth: 200, svgHeight: '30%',
svgStroke: 'aqua', svgStrokeWidth: '+=7',
svgTransform: 'rotate(60, 100, 75)'}, 2000);
Animate
or a combination of effects
$('#svganim').svg({onLoad: drawAnim});
var current = {};
$('#animGo').click(function() {
var opt = $('#animShape').val();
$('#animBetween').text(
'between ' + values[opt][0] + ' and ' + values[opt][1]);
current[opt] = 1 - (current[opt] || 0);
var parts = opt.split(':');
var params = {};
params['svg' + parts[1]] = values[opt][current[opt]];
$(shapes[parts[0]]).animate(params, 2000);
});
$('#animCombo').toggle(function() {
$(shapes['rect']).animate(
{svgWidth: '30%', svgStrokeWidth: 10,
svgTransform: 'rotate(45 100 75) translate(20 40)'}, 2000);
$(shapes['circle']).animate({svgR: 100, svgStroke: 'pink'}, 2000);
}, function() {
$(shapes['rect']).animate(
{svgWidth: '25%', svgStrokeWidth: 3,
svgTransform: 'rotate(0 100 75) translate(0 0)'}, 2000);
$(shapes['circle']).animate({svgR: 50, svgStroke: 'red'}, 2000);
});
The attributes that can be animated are summarised below. For more information see the documentation reference animation page
| SVG Attribute | Animation Attribute | Type | Elements |
|---|---|---|---|
| x | svgX | numeric | svg, rect, text |
| y | svgY | numeric | svg, rect, text |
| width | svgWidth | numeric | svg, rect |
| height | svgHeight | numeric | svg, rect |
| cx | svgCx | numeric | circle, ellipse |
| cy | svgCy | numeric | circle, ellipse |
| r | svgR | numeric | circle |
| rx | svgRx | numeric | rect, ellipse |
| ry | svgRy | numeric | rect, ellipse |
| x1 | svgX1 | numeric | line |
| y1 | svgY1 | numeric | line |
| x2 | svgX2 | numeric | line |
| y2 | svgY2 | numeric | line |
| opacity | svgOpacity | numeric 0.0-1.0 | group, rect, circle, ellipse, line, polyline, polygon, path, text |
| font-size | svgFontSize | numeric | group, text |
| font-weight | svgFontWeight | numeric | group, text |
| letter-spacing | svgLetterSpacing | numeric | group, text |
| word-spacing | svgWordSpacing | numeric | group, text |
| fill | svgFill | colour | group, rect, circle, ellipse, polygon, path, text |
| fill-opacity | svgFillOpacity | numeric 0.0-1.0 | group, rect, circle, ellipse, polygon, path, text |
| stroke | svgStroke | colour | group, rect, circle, ellipse, line, polyline, polygon, path, text |
| stroke-width | svgStrokeWidth | numeric | group, rect, circle, ellipse, line, polyline, polygon, path, text |
| stroke-dasharray | svgStrokeDashArray | string | group, rect, circle, ellipse, line, polyline, polygon, path, text |
| stroke-dashoffset | svgStrokeDashOffset | numeric | group, rect, circle, ellipse, line, polyline, polygon, path, text |
| stroke-opacity | svgStrokeOpacity | numeric 0.0-1.0 | group, rect, circle, ellipse, line, polyline, polygon, path, text |
| transform | svgTransform | string | group, rect, circle, ellipse, line, polyline, polygon, path, text |
| viewBox | svgViewBox | string | svg, symbol, marker, pattern |
Select a shape and its appearance and then drag in the panel to create it.
var drawNodes = [];
var sketchpad = null;
var start = null;
var outline = null;
var offset = null;
$('#svgsketch').svg({onLoad: function(svg) {
sketchpad = svg;
var surface = svg.rect(0, 0, '100%', '100%', {id: 'surface', fill: 'white'});
$(surface).mousedown(startDrag).mousemove(dragging).mouseup(endDrag);
resetSize(svg, '100%', '100%');
}
});
/* Remember where we started */
function startDrag(event) {
offset = ($.browser.msie ? {left: 0, top: 0} : $('#svgsketch').offset());
if (!$.browser.msie) {
offset.left -= document.documentElement.scrollLeft || document.body.scrollLeft;
offset.top -= document.documentElement.scrollTop || document.body.scrollTop;
}
start = {X: event.clientX - offset.left, Y: event.clientY - offset.top};
event.preventDefault();
}
/* Provide feedback as we drag */
function dragging(event) {
if (!start) {
return;
}
if (!outline) {
outline = sketchpad.rect(0, 0, 0, 0,
{fill: 'none', stroke: '#c0c0c0', strokeWidth: 1, strokeDashArray: '2,2'});
$(outline).mouseup(endDrag);
}
sketchpad.change(outline, {x: Math.min(event.clientX - offset.left, start.X),
y: Math.min(event.clientY - offset.top, start.Y),
width: Math.abs(event.clientX - offset.left - start.X),
height: Math.abs(event.clientY - offset.top - start.Y)});
event.preventDefault();
}
/* Draw where we finish */
function endDrag(event) {
if (!start) {
return;
}
$(outline).remove();
outline = null;
drawShape(start.X, start.Y,
event.clientX - offset.left, event.clientY - offset.top);
start = null;
event.preventDefault();
}
/* Draw the selected element on the canvas */
function drawShape(x1, y1, x2, y2) {
var left = Math.min(x1, x2);
var top = Math.min(y1, y2);
var right = Math.max(x1, x2);
var bottom = Math.max(y1, y2);
var settings = {fill: $('#fill').val(), stroke: $('#stroke').val(),
strokeWidth: $('#swidth').val()};
var shape = $('#shape').val();
var node = null;
if (shape == 'rect') {
node = sketchpad.rect(left, top, right - left, bottom - top, settings);
}
else if (shape == 'circle') {
var r = Math.min(right - left, bottom - top) / 2;
node = sketchpad.circle(left + r, top + r, r, settings);
}
else if (shape == 'ellipse') {
var rx = (right - left) / 2;
var ry = (bottom - top) / 2;
node = sketchpad.ellipse(left + rx, top + ry, rx, ry, settings);
}
else if (shape == 'line') {
node = sketchpad.line(x1, y1, x2, y2, settings);
}
else if (shape == 'polyline') {
node = sketchpad.polyline([[(x1 + x2) / 2, y1], [x2, y2],
[x1, (y1 + y2) / 2], [x2, (y1 + y2) / 2], [x1, y2],
[(x1 + x2) / 2, y1]], $.extend(settings, {fill: 'none'}));
}
else if (shape == 'polygon') {
node = sketchpad.polygon([[(x1 + x2) / 2, y1], [x2, y1], [x2, y2],
[(x1 + x2) / 2, y2], [x1, (y1 + y2) / 2]], settings);
}
drawNodes[drawNodes.length] = node;
$(node).mousedown(startDrag).mousemove(dragging).mouseup(endDrag);
$('#svgsketch').focus();
};
/* Remove the last drawn element */
$('#undo').click(function() {
if (!drawNodes.length) {
return;
}
sketchpad.remove(drawNodes[drawNodes.length - 1]);
drawNodes.splice(drawNodes.length - 1, 1);
});
/* Clear the canvas */
$('#clear2').click(function() {
while (drawNodes.length) {
$('#undo').trigger('click');
}
});
/* Convert to text */
$('#toSVG').click(function() {
alert(sketchpad.toSVG());
});
Use the graphing extension to make it easier to create SVG graphs.
Add the jQuery SVG graphing extension in the head section of your page.
<script type="text/javascript" src="jquery.svggraph.js"></script>
Then access the extra functionality via the
graph object within the SVG root. As well as the series and their formatting,
you can control the graph title, axes, gridlines, labels, and legend.
with legend and background
Options:
This is the code behind the graphing.
$('#svggraph').svg(initGraph);
var chartAreas = [[0.1, 0.1, 0.95, 0.9], [0.2, 0.1, 0.95, 0.9],
[0.1, 0.1, 0.8, 0.9], [0.1, 0.25, 0.9, 0.9], [0.1, 0.1, 0.9, 0.8]];
var legendAreas = [[0.0, 0.0, 0.0, 0.0], [0.005, 0.1, 0.125, 0.5],
[0.85, 0.1, 0.97, 0.5], [0.2, 0.1, 0.8, 0.2], [0.2, 0.9, 0.8, 0.995]];
var fills = [['lightblue', 'url(#fadeBlue)'], ['pink', 'url(#fadeRed)'],
['lightgreen', 'url(#fadeGreen)']];
function initGraph(svg) {
var defs = svg.defs();
svg.linearGradient(defs, 'fadeBlue',
[[0, 'lightblue'], [1, 'blue']]);
svg.linearGradient(defs, 'fadeRed', [[0, 'pink'], [1, 'red']]);
svg.linearGradient(defs, 'fadeGreen',
[[0, 'lightgreen'], [1, 'green']]);
svg.graph.noDraw().title('Browser Usage', 'blue').
addSeries('IE', [95.97, 91.80, 88.16, 86.64],
'lightblue', 'blue', 3).
addSeries('Netscape', [3.39, 2.83, 1.61, 0.00],
'pink', 'red', 3).
addSeries('Firefox', [0.00, 4.06, 8.13, 9.95],
'lightgreen', 'green', 3).
format('ivory', 'gray').
gridlines({stroke: 'gray', strokeDashArray: '2,2'}, 'gray');
svg.graph.xAxis.title('Year', 'green').scale(0, 3).
ticks(1, 0).labels(['2002', '2004', '2005', '2006']);
svg.graph.yAxis.title('Percentage').ticks(10, 5);
svg.graph.legend.settings({fill: 'lightgoldenrodyellow',
stroke: 'gray'});
svg.graph.status(showGraphStatus);
}
/* Draw a new graph with the selected options */
$('#graphIt').click(function() {
var chartType = $('#chartType').val();
var chartLegend = parseInt($('#chartLegend').val(), 10);
var seriesFill = ($('#seriesFill').val() == 'plain' ? 0 : 1);
var svg = $('#svggraph').svg('get');
svg.graph.noDraw().
legend.show(chartLegend).area(legendAreas[chartLegend]).end().
series(0).format(fills[0][seriesFill]).end().
series(1).format(fills[1][seriesFill]).end().
series(2).format(fills[2][seriesFill]).end().
area(chartAreas[chartLegend]).
type(chartType, {explode: 2, explodeDist: 10}).redraw();
chartType = $.svg.graphing.chartTypes()[chartType];
$('#graphDesc').text(chartType.description());
var options = '';
for (var i = 0; i < chartType.options().length; i++) {
options += '<li>' + chartType.options()[i] + '</li>';
}
$('#graphOptions').html(options || '<li>None</li>');
resetSize(svg);
});
function showGraphStatus(label, value) {
$('#svggraph').attr('title', (label ? label + ' ' + value : ''));
}
Use the plotting extension to display the plots of numeric functions on a grid.
Add the jQuery SVG plotting extension in the head section of your page.
<script type="text/javascript" src="jquery.svgplot.js"></script>
Then access the extra functionality via the
plot object within the SVG root. As well as the functions and their formatting,
you can control the plot title, axes, gridlines, labels, and legend.
Zoom with x/y units and legend
This is the code behind the plotting.
$('#svgplot').svg(initPlot);
var plotZooms = [[-2, 2, -1.5, 1.5], [-10, 10, -10, 10]];
var chartAreas = [[0.1, 0.1, 0.95, 0.9], [0.2, 0.1, 0.95, 0.9],
[0.1, 0.1, 0.8, 0.9], [0.1, 0.25, 0.9, 0.9], [0.1, 0.1, 0.9, 0.8]];
var legendAreas = [[0.0, 0.0, 0.0, 0.0], [0.005, 0.1, 0.125, 0.5],
[0.85, 0.1, 0.97, 0.5], [0.2, 0.1, 0.8, 0.2], [0.2, 0.9, 0.8, 0.995]];
function initPlot(svg) {
svg.plot.noDraw().title('Functions', 'blue').
addFunction('Sine', Math.sin, 'blue', 3).
addFunction('Cosine', Math.cos, [-Math.PI, Math.PI], 20, 'red', 3).
addFunction('Decaying', decay, 'green', 3).
format('ivory', 'gray').
gridlines({stroke: 'gray', strokeDashArray: '2,2'}, 'gray');
svg.plot.xAxis.scale(-1, 3.5).ticks(1, 0.2);
svg.plot.yAxis.scale(-1.5, 1.5).ticks(1, 0.2);
svg.plot.legend.settings({fill: 'lightgoldenrodyellow',
stroke: 'gray'});
svg.plot.status(showPlotStatus);
}
/* Plot a new function with the selected options */
$('#plotIt').click(function() {
var plotZoom = parseInt($('#plotZoom').val(), 10);
var plotEqual = parseInt($('#plotEqual').val(), 10);
var plotLegend = parseInt($('#plotLegend').val(), 10);
var svg = $('#svgplot').svg('get');
svg.plot.noDraw().
legend.show(plotLegend).area(legendAreas[plotLegend]).end().
xAxis.scale(plotZooms[plotZoom][0], plotZooms[plotZoom][1]).end().
yAxis.scale(plotZooms[plotZoom][2], plotZooms[plotZoom][3]).end().
area(chartAreas[plotLegend]).equalXY(plotEqual).redraw();
resetSize(svg);
});
/* Decaying sine wave */
function decay(x) {
return Math.exp(-0.4 * x) * Math.sin(x);
}
function showPlotStatus(label) {
$('#svgplot').attr('title', label);
}
You can combine graphs, plots, and other SVG elements in the one document.
A default container (embedded <svg>) is created for each of a graph
and a plot. You can change the settings for these or specify a new
container and size and position it appropriately.
This is the code behind the mixture.
$('#svgmix').svg({onLoad: drawMixture});
function drawMixture(svg) {
var g = svg.group({'font-weight': 'bold'});
svg.text(g, 600, 100, 'This graph is in its');
svg.text(g, 600, 120, 'own <svg> element');
svg.text(g, 150, 450, 'As is this plot');
svg.change(svg.graph.container(), /* Graph */
{width: 600, height: 350, 'font-size': 12});
svg.graph.noDraw().
title('Browser Usage').type('column').area([0.1, 0.1, 0.9, 0.8]).
addSeries('IE', [95.97, 91.80, 88.16, 86.64],
'lightblue', 'blue', 3).
addSeries('Netscape', [3.39, 2.83, 1.61, 0.00], 'pink', 'red', 3).
addSeries('Firefox', [0.00, 4.06, 8.13, 9.95],
'lightgreen', 'green', 3).
format('ivory', 'gray').
gridlines({stroke: 'gray', strokeDashArray: '2,2'}, 'gray').
xAxis.title('Year', 30).scale(0, 3).
ticks(1, 0).labels(['2002', '2004', '2005', '2006']).end().
yAxis.title('Percentage').ticks(10, 5).end().
legend.show(true).area([0.2, 0.9, 0.8, 0.995]).
settings({fill: 'lightgoldenrodyellow', stroke: 'gray'}).end().
redraw();
svg.plot.noDraw().container(svg.svg(300, 350, 400, 350)). /* Plot */
title('Functions').area([0.1, 0.1, 0.9, 0.8]).equalXY(true).
addFunction('Sine', Math.sin, 'blue', 3).
addFunction('Cosine', Math.cos, [-Math.PI, Math.PI], 20, 'red', 3).
addFunction('Decaying', decay, 'green', 3).
format('ivory', 'gray').
gridlines({stroke: 'gray', strokeDashArray: '2,2'}, 'gray').
xAxis.scale(-1, 3.5).ticks(1, 0.2).end().
yAxis.scale(-1.5, 1.5).ticks(1, 0.2).end().
legend.show(true).area([0.1, 0.9, 0.9, 0.995]).
settings({fill: 'lightgoldenrodyellow', stroke: 'gray'}).end().
redraw();
resetSize(svg, 800, 700);
}
/* Decaying sine wave */
function decay(x) {
return Math.exp(-0.4 * x) * Math.sin(x);
}
The SVG DOM is different to the HTML DOM for which jQuery was designed.
In particular, any attributes that can be animated are stored as objects
instead of plain strings. This includes the class attribute.
Thus, jQuery's functions that work with classes don't work on SVG nodes.
To overcome this problem you can use the jQuery SVG DOM extension. Add the extension in the head section of your page.
<script type="text/javascript" src="jquery.svgdom.js"></script>
Then just use jQuery's class and attribute functions on SVG nodes as well:
addClass, removeClass, toggleClass,
hasClass, attr, and removeAttr.
Use the power of jQuery to select nodes in the SVG document with this extension. Provide the SVG root element as the context for your selections:
$(selector, svg.root())...
Unfortunately, there are some small modifications needed to the base jQuery code for IE that cannot be overridden in the extension. A modified jQuery 1.7.2 is available for download, as is a modified jQuery 1.6.2, modified jQuery 1.5.1, modified jQuery 1.4.2, and modified jQuery 1.3.2.
In the jQuery.removeData function (line 1881, v1.7.2):
if ( jQuery.support.deleteExpando ) {
delete elem[ internalKey ];
} else {
try { // SVG
elem.removeAttribute( internalKey );
} catch (e) {
elem[ internalKey ] = null;
}
}
In the event.add function (line 2985, v1.7.2):
if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
// Bind the global event handler to the element
try { // SVG
elem.addEventListener( type, eventHandle, false );
} catch(e) {
if ( elem.attachEvent ) {
elem.attachEvent( "on" + type, eventHandle );
}
}
}
In the event.remove function (line 3074, v1.7.2):
if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) {
try { // SVG
elem.removeEventListener(type, elemData.handle, false);
}
catch (e) {
if (elem.detachEvent) {
elem.detachEvent("on" + type, elemData.handle);
}
}
}
In the event.fix function (line 3394, v1.7.2):
if (event.target.namespaceURI == 'http://www.w3.org/2000/svg') { // SVG
event.button = [1, 4, 2][event.button];
}
// Add which for click: 1 === left; 2 === middle; 3 === right
// Note: button is not normalized, so don't use it
if ( !event.which && button !== undefined ) {
event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );
}
In the Sizzle function (line 4083, v1.7.2):
if ( toString.call(checkSet) === "[object Array]" ) {
if ( !prune ) {
results.push.apply( results, checkSet );
} else if ( context && context.nodeType === 1 ) {
for ( i = 0; checkSet[i] != null; i++ ) {
if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) {
results.push( set[i] || set.item(i) ); // SVG
}
}
} else {
for ( i = 0; checkSet[i] != null; i++ ) {
if ( checkSet[i] && checkSet[i].nodeType === 1 ) {
results.push( set[i] || set.item(i) ); // SVG
}
}
}
} else {...
In the fallback for the Sizzle makeArray function (line 4877, v1.7.2):
if ( toString.call(array) === "[object Array]" ) {
Array.prototype.push.apply( ret, array );
} else {
if ( typeof array.length === "number" ) {
for ( var l = array.length; i < l; i++ ) {
ret.push( array[i] || array.item(i) ); // SVG
}
} else {
for ( ; array[i]; i++ ) {
ret.push( array[i] );
}
}
}
In the jQuery.cleandata function (line 6538, v1.7.2):
if ( deleteExpando ) {
delete elem[ jQuery.expando ];
} else {
try { // SVG
elem.removeAttribute( jQuery.expando );
} catch (e) {
// Ignore
}
}
In the fallback getComputedStyle function (line 6727, v1.7.2):
defaultView = (elem.ownerDocument ? elem.ownerDocument.defaultView : elem.defaultView); // SVG
if ( defaultView &&
(computedStyle = defaultView.getComputedStyle( elem, null )) ) {
ret = computedStyle.getPropertyValue( name );
...
The structure of the sample SVG document below is as follows:
Select
and fill with
or or click/mouseover
$('#svgselect').svg({onLoad: function(svg) {
svg.rect(10, 20, 150, 100, {id: 'rect1',
fill: 'red', stroke: 'black', strokeWidth: 3});
svg.circle(100, 150, 75, {id: 'circle1',
fill: 'yellow', stroke: 'black', strokeWidth: 3});
var g = svg.group({transform: 'translate(200,20)'});
svg.circle(g, 100, 100, 75, {id: 'circle2', class_: 'grouped',
fill: 'yellow', stroke: 'black', strokeWidth: 3});
svg.rect(g, 10, 150, 150, 100, {id: 'rect2', class_: 'grouped',
fill: 'red', stroke: 'black', strokeWidth: 3});
resetSize(svg, '100%', '100%');
}
});
$('#selectPath').change(function() {
$('#selector').val($(this).val());
});
$('#fillButton').click(function() {
var svg = $('#svgselect').svg('get');
$($('#selector').val(), svg.root()).attr('fill', $('#selectColour').val());
});
$('#eventButton').click(function() {
var svg = $('#svgselect').svg('get');
if ($('#selectEventAdd').is(':checked')) {
$($('#selector').val(), svg.root()).bind('click', svgClicked).
bind('mouseover', svgOver).bind('mouseout', svgOut);
}
else {
$($('#selector').val(), svg.root()).
unbind('click mouseover mouseout');
}
});
function svgClicked() {
alert('This is a ' + $(this).attr('fill') + ' ' + this.nodeName);
}
function svgOver() {
$(this).attr('stroke', 'lime');
}
function svgOut() {
$(this).attr('stroke', 'black');
}
Since IE requires the ascynchronous loading of a seed SVG document,
you should not try to access the SVG components immediately after
attaching this plugin to a division. Instead, make use of the
onLoad callback to ensure that the SVG component
is ready when you want to use it.
Since SVG is XML, you can use the power of jQuery on it as well. Retrieve the SVG wrapper as usual, then work with respect to its root element. For example, to change the line colour for all circles in a container:
var svg = $('#mycontainer').svg('get');
$('circle', svg.root()).attr('stroke', 'red');
Note, however, that jQuery is designed for the HTML DOM and that the SVG DOM is different and some things do not work. For example, the class names in SVG are actually objects rather than the simple strings of HTML, since they can be animated. This means that the class selector of jQuery doesn't work. The SVG DOM extension adds SVG support for the class and attribute functions of jQuery and for jQuery selectors over SVG nodes.
You can also access jQuery from JavaScript embedded within the SVG. First, you need to break out of the SVG document back into the containing page, and then use jQuery as usual. For example, in response to a click event, change the colour of all circles in the document:
var jQ = (window.parent ? window.parent.jQuery : window.jQuery);
var svg = jQ(event.target).parents('svg');
jQ('circle', svg).attr('fill', 'blue');You can even use this plugin from within a standalone SVG document.
After loading the jQuery and plugin code, you need an onload
handler to initialise the SVG wrapper, passing it a reference to the root
SVG element and an object providing the expected width and height.
The example below shows all of this and draws a plus sign
in the top-left corner of the canvas.
<svg onload="init(evt)" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<script type="text/javascript" xlink:href="jquery-1.2.6.js"></script>
<script type="text/javascript" xlink:href="jquery.svg.js"></script>
<script type="text/javascript"><![CDATA[
var svgWrapper;
function init(evt) {
svgWrapper = new $.svg._wrapperClass(
evt.target.ownerDocument.documentElement,
{clientWidth: 500, clientHeight: 400});
svgWrapper.rect(40, 45, 50, 10);
svgWrapper.rect(60, 25, 10, 50);
}
// ]]>
</script>
<g>
</g>
</svg>
Note, however, that jQuery 1.3.x doesn't work within standalone SVG documents due to the introduction of feature detection.
This tab highlights examples of this plugin in use "in the wild".
Dance KaleidoscopeTo help visualise the dances performed by this group, this page provides animations of various dances using SVG.
A Java Web application that generates SVG data model diagrams for any database with a JDBC driver. jQuery SVG helps manage the diagram on the Web page.
A rendering of the setup and results for the double-slit experiment.
Three examples of using the plugin.
Webbanner24In this application you can create SVG banner graphics which are also exported as raster graphics. You can choose several fonts and cliparts and you can drag around and position the elements whereever you like. Most of the functions were created with the help of the plugin.
To add another example, please contact me (kbwood{at}iinet.com.au) and provide the plugin name, the URL of your site, its title, and a short description of its purpose and where/how the plugin is used.
A list of available fields and functions. For more detail see the documentation reference page.
$(selector).svg({
loadURL: '', // External document to load
onLoad: null, // Callback once loaded
settings: {}, // Additional settings for SVG element
initPath: ''}) // Initial path for blank document
$(selector).svg(loadURL)
$(selector).svg(onLoad)
$(selector).svg('get') // Retrieve SVG wrapper
$(selector).svg('destroy') // Remove SVG functionality
$.svg.addExtension(name, extClass) // Extend SVG functionality
$.svg.isSVGElem(node)
svg.root()
svg.configure(node, settings, clear)
svg.getElementById(id)
svg.change(element, settings)
svg.title(parent, text, settings)
svg.describe(parent, text, settings)
svg.defs(parent, id, settings)
svg.symbol(parent, id, x1, y1, width, height, settings)
svg.marker(parent, id, refX, refY, mWidth, mHeight, orient, settings)
svg.style(parent, styles, settings)
svg.script(parent, script, type, settings)
svg.linearGradient(parent, id, stops, x1, y1, x2, y2, settings)
svg.radialGradient(parent, id, stops, cx, cy, r, fx, fy, settings)
svg.pattern(parent, id, x, y, width, height, vx, vy, vwidth, vheight, settings)
svg.clipPath(parent, id, units, settings)
svg.mask(parent, id, x, y, width, height, settings)
svg.createPath()
svg.createText()
svg.svg(parent, x, y, width, height, vx, vy, vwidth, vheight, settings)
svg.group(parent, id, settings)
svg.use(parent, x, y, width, height, ref, settings)
svg.link(parent, ref, settings)
svg.image(parent, x, y, width, height, ref, settings)
svg.path(parent, path, settings)
svg.rect(parent, x, y, width, height, rx, ry, settings)
svg.circle(parent, cx, cy, r, settings)
svg.ellipse(parent, cx, cy, rx, ry, settings)
svg.line(parent, x1, y1, x2, y2, settings)
svg.polyline(parent, points, settings)
svg.polygon(parent, points, settings)
svg.text(parent, x, y, value, settings)
svg.textpath(parent, path, value, settings)
svg.other(parent, name, settings)
svg.add(parent, node)
svg.clone(parent, node)
svg.load(url, settings)
svg.remove(node)
svg.clear(attrsToo)
svg.toSVG(node)
path.reset()
path.move(x, y, relative)
path.line(x, y, relative)
path.horiz(x, relative)
path.vert(y, relative)
path.curveC(x1, y1, x2, y2, x, y, relative)
path.smoothC(x2, y2, x, y, relative)
path.curveQ(x1, y1, x, y, relative)
path.smoothQ(x, y, relative)
path.arc(rx, ry, xRotate, large, clockwise, x, y, relative)
path.close()
path.path()
text.reset()
text.string(value)
text.span(value, settings)
text.ref(id, settings)
text.path(id, value, settings)
Great work. Congratulations! I am excited to see your good work.
Love the jquery svg extension you've written. Stunningly neat.
Thanks for this plugin and it's documentation filled with examples. Learning by example was always my preferred way to learn.
We have been long-time SVG advocates and active with Inkscape. So love the idea of an easy to use SVG ajax plugin.
This is an amazing plugin! It has so many applications.
I am still amazed how quickly I have put something together using your plugin and the flexibility of SVG's.
Contact Keith Wood at kbwood{at}iinet.com.au with comments or suggestions.
| Version | Date | Changes |
|---|---|---|
| 1.4.5 | 28 Apr 2012 |
|
| 1.4.4 | 23 Jul 2011 |
|
| 1.4.3 | 23 Jan 2010 |
|
| 1.4.2 | 05 Sep 2009 |
|
| 1.4.1 | 18 Jul 2009 |
|
| 1.4.0 | 06 Jun 2009 |
|
| 1.3.2 | 28 Mar 2009 |
|
| 1.3.1 | 24 Jan 2009 |
|
| 1.3.0 | 13 Dec 2008 |
|
| 1.2.1 | 23 Aug 2008 |
|
| 1.2.0 | 19 Jul 2008 |
|
| 1.1.1 | 14 Jun 2008 |
|
| 1.1.0 | 07 Jun 2008 |
|
| 1.0.1 | 05 May 2008 |
|
| 1.0.0 | 14 Sep 2007 |
|