Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Embedding external SVG in HTML for JavaScript manipulation

I have a SVG image, showing geographical regions. http://upload.wikimedia.org/wikipedia/commons/7/71/Nederland_gemeenten_2009.svg

I want to display the SVG image on a webpage, and using a combination of JavaScript and CSS to interact with the image. (ie, detect clicks on a region, setting a different background color for a region).

I know this question is asked several times on StackOverflow, but I cannot find a complete code sample to work on further. Any recommendations on JavaScript packages, like jQuery, or plug-ins are welcome.

like image 740
Gerrit Avatar asked Dec 28 '12 10:12

Gerrit


People also ask

How do I embed an external SVG in HTML?

SVG images can be written directly into the HTML document using the <svg> </svg> tag. To do this, open the SVG image in VS code or your preferred IDE, copy the code, and paste it inside the <body> element in your HTML document. If you did everything correctly, your webpage should look exactly like the demo below.

Can SVG integrate with JavaScript?

Like HTML, SVGs are represented using the Document Object Model (DOM) and so can be manipulated with Javascript relatively easily, especially if you are familiar with using JS with HTML. All the code examples can be found by following the Github link at the top of this post.

Is SVG JavaScript dependent?

SVGs are considered to be more accessible as they support text, and canvas is dependent on Javascript. So, the event that the browser does not support SVG but still text can be displayed. If Javascript has been disabled, then the device cannot be able to interpret the javascript output.

Can I use SVG in IMG tag?

The quick way: img elementTo embed an SVG via an <img> element, you just need to reference it in the src attribute as you'd expect. You will need a height or a width attribute (or both if your SVG has no inherent aspect ratio).


1 Answers

My understanding of the question is that there are different aspects to be solved:

  1. How to prepare the image for interaction
  2. How to embed the image in the page
  3. How to use CSS with SVG
  4. How to use JavaScript for interaction

Preparing the image

First of all, I'd recommend to clean up the image. Inkscape leaves all kind of stuff there that you don't need, which includes elements and attributes in the sodipodi: and inkscape: namespaces as well as repetitive and/or redundant style attributes. You don't have to remove that, but it saves you some bandwidth/loading time, and if you want to work with CSS stylesheets, than the style attributes are in your way.

In your example file, you have 472 times the same style attribute. Remove all of them and create an equivalent CSS rule once.

You might also add some info about the municipalities to the markup. You could e.g. change the IDs of each path representing a municipality according to its name. You could also use a data-* attribute for this purpose. The latter has the advantage that you can use spaces. See below for how this is useful for interaction, especially with CSS.

Embedding the image

I'd recommend using the SVG inline, especially if you want to interact with CSS/JavaScript. This means, you just add the SVG markup to your HTML, or you load and insert it using Ajax. The latter has the benefit that the surrounding page loads faster and feels more responsive.

An example of an inline SVG element:

<div id="svgContainer">   <!-- This is an HTML div, and inside goes the SVG -->   <svg xmlns="http://www.w3.org/2000/svg" width="100px" height="100px">     <circle r="50" cx="50" cy="50" fill="green"/>   </svg> </div> 

A simplified example of how to load SVG using Ajax:

xhr = new XMLHttpRequest(); xhr.open("GET","my.svg",false); // Following line is just to be on the safe side; // not needed if your server delivers SVG with correct MIME type xhr.overrideMimeType("image/svg+xml"); xhr.onload = function(e) {   // You might also want to check for xhr.readyState/xhr.status here   document.getElementById("svgContainer")     .appendChild(xhr.responseXML.documentElement); }; xhr.send(""); 

How to use CSS

SVG can be styled just like HTML. Of course, SVG has it's own set of properties, like fill-opacity or stroke-dasharray and does not support a lot of HTML's properties, like margin, position or the like. But the selector mechanisms are 100% the same.

You can mix the CSS for your inline SVG with the CSS for your HTML, either inside a <style> element or an external CSS file. You can also use the <style> element inside the SVG code and style attributes.

Assuming you gave your SVG elements meaningful IDs or data-* attributes, two ways of highlighting municipalities using CSS would be:

#Bronckhorst, #Laarbeek {fill:red} 

or

*[data-gemeente=Bronckhorst], *[data-gemeente=Laarbeek] {fill:red} 

Or, of course, you can change the style attributes of the respective elements. Properties are also supported as attribute, i.e. style="stroke-width:2" can also be specified like stroke-width="2". If the same property is set using both an attribute and CSS (either using the style attribute, a style element or an external stylesheet), the CSS overrides the attribute.

JavaScript interaction

There is basically no difference between HTML and SVG regarding JavaScript interaction, at least as long as you use plain vanilla DOM. This means, HTML specific features like innerHTML are not supported in SVG (i.e. there is no innerSVG). But SVG has its own graphics specific set of DOM methods (see the W3C specs).

One thing to be aware of is the work with namespaces. All SVG elements should be in the SVG namespace, and when creating them using JavaScript, createElementNS() has to be used instead of createElement():

var use = document.createElementNS("http://www.w3.org/2000/svg","use") 

Likewise, attributes in the XLink namespace (namely xlink:href) have to be manipulated using setAttributeNS() instead of setAttribute():

use.setAttributeNS("http://www.w3.org/1999/xlink","href","#foo") 

As libraries like jQuery partly rely on HTML specific features, it's safer to avoid them when manipulating SVG. [EDIT: The situation might have improved since I wrote this answer. Not being a jQuery user, I don't know how well it works nowadays.] There are also SVG specific libraries like D3.js which can be useful for specific purposes and are worth a look. (I'm doing D3.js injustice when simply calling it an SVG specific library, because it's more).

You can use onclick and similar attributes and standard DOM addEventListener(). A very simple example of using JavaScript events would be to add an event listener to the <svg> element that reports the name of a municipality that a user clicked on:

document.getElementsByTagName("svg")[0]   .addEventListener("click",function(evt){     alert(evt.target.getAttribute("data-gemeente"))   },   false) 

Side note: Toopltips The same effect that you get using the title attribute in HTML can be achieved using the <title> element in SVG. Just put a <title> element inside an SVG element and on hover, you see a tooltip with the content of the <title> element.

<svg xmlns="http://www.w3.org/2000/svg" width="100px" height="100px">   <rect width="100" height="100">     <title>test</title>   </rect> </svg> 
like image 137
Thomas W Avatar answered Oct 05 '22 15:10

Thomas W