bokan
bokan

Reputation: 3692

Why SVG use element created with JavaScript is not shown?

I have a SVG in my document and I add a symbol to it with JavaScript like this:

var myScene =document.getElementById('myScene');
var useSVG = document.createElement('use');
useSVG.setAttribute('xlink:href','spriteSheet.svg#mySymbol');
useSVG.setAttribute('x','10');
useSVG.setAttribute('y','30');
useSVG.setAttribute('width','10');
useSVG.setAttribute('height','10');
myScene.appendChild(useSVG);

The symbol does not show up whereas the resulting code is exactly the same as another node written in HTML which is displayed correctly.

Code shown in debugger:

<svg id="myScene" width="200px" height="200px">
    <use xlink:href="spriteSheet.svg#mySymbol" x="5" y="50" width="10" height="10"></use>
    <!-- this one was in html, it is visible -->
    <use xlink:href="spriteSheet.svg#mySymbol" x="10" y="30" width="10" height="10"></use>
    <!-- this one is added with javascript. it is not displayed -->
</svg>

Upvotes: 13

Views: 3007

Answers (4)

MiftikCZ
MiftikCZ

Reputation: 61

I had exactly the same problem and I just figured it out! When creating the svg element with document.createElement("svg"), you just have to use the correct namespace. And it works even with other elements like path, line, rect etc

So this

document.createElement("svg");

Becomes that

document.createElementNS("http://www.w3.org/2000/svg","svg");

And this

document.createElement("use");

Becomes that

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

In case you wondering, you don't have to use element.setAttributeNS, element.setAttribute will work

Upvotes: 1

Kevin Sterns
Kevin Sterns

Reputation: 114

In general, to create SVG elements you must use createElementNS(), not createElement(). But even then, createElementNS() won't properly create an SVG "use" element. It appears to work, but the resulting "use" won't be displayed.

Workaround 1: clone an existing "use" element, then modify it via setAttributeNS(). (In my experience, setAttribute() also works on SVG elements.)

var useSVG = another_useSVG.cloneNode(true);
myScene.appendChild(useSVG);
useSVG.setAttribute('xlink:href','spriteSheet.svg#mySymbol');

Workaround 2: create a group element, then assign it's innerHTML to get the desired "use" element.

var myScene = document.getElementById('myScene');
var group = document.createElementNS('http://www.w3.org/2000/svg', 'g');
group.innerHTML = "<use xlink:href='spriteSheet.svg#mySymbol' x='10' y='30' width='10' height='10'/>";

Upvotes: 0

Paul LeBeau
Paul LeBeau

Reputation: 101938

You need to use createElementNS() to create SVG elements. The basic createElement() creates elements in the HTML namespace. So you basically have been creating <html:use> elements instead of <svg:use> ones.

var myScene =document.getElementById('myScene');
var useSVG = document.createElementNS('http://www.w3.org/2000/svg', 'use');
useSVG.setAttributeNS('http://www.w3.org/1999/xlink','href','spriteSheet.svg#mySymbol');
useSVG.setAttribute('x','10');
useSVG.setAttribute('y','30');
useSVG.setAttribute('width','10');
useSVG.setAttribute('height','10');
myScene.appendChild(useSVG);

Demo here

Update

I have just realised there is a second problem with your code. You are using an external reference in your href (it's referenceing a symbol in another file). It seems IE doesn't support external references.

I found more info, and a possible workaround, here: http://css-tricks.com/svg-use-external-source/

Upvotes: 19

philipp
philipp

Reputation: 16505

I am not sure to 100% but I think you need to set the xlink:href Attribute using setAttributeNS() like this:

useSVG.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', 'spriteSheet.svg#mySymbol');

Also make sure that the namespace is declared within your document.

<html xmlns:xlink="http://www.w3.org/1999/xlink">

<!-- or if standalone svg -->

<svg xmlns:xlink="http://www.w3.org/1999/xlink">

However, this way I solved the same issue within an xhtml document, probably that will work for html5 or standalone SVG, too.

xlink specification

good luck!

Upvotes: 3

Related Questions