Reputation: 71
I try to dynamically create svg path elements in html using JavaScript.
I want to set the paths in a <defs>
element that later can be reused in <use>
xlink:href elements.
After creation (press button in the example) the lower part of the screen remains empty.
The same html, when placed statically works fine. (above the button)
Inspecting in Chrome/Firefox reveals that in the dynamically manipulated dom the #shadow-root (node?) is empty in the dynamically created part whereas it's holding a copy of the path in the static part.
Is there a way to trigger a manual refresh, that I have missed?
Is this generally a forbidden way?
Is there a mistake I made in my code?
<!DOCTYPE html>
<html>
<script>
function test() {
component = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
component.classList.add("component");
component.style.left = '0px';
component.style.top = '0px';
component.style.width = '800px';
component.style.height = '400px';
component.style.position = "absolute";
document.getElementById("theConnections").appendChild(component);
defs = document.createElementNS('http://www.w3.org/2000/svg', 'defs');
component.appendChild(defs);
pathdef = document.createElementNS('http://www.w3.org/2000/svg', 'path');
pathdef.id = "conn1";
pathdef.setAttribute("d", "M264 133 L396 132");
defs.appendChild(pathdef);
path2 = document.createElementNS('http://www.w3.org/2000/svg', 'use');
path2.setAttribute("xlink:href", "#conn1");
path2.setAttribute("stroke", "black");
path2.setAttribute("stroke-width", "9");
component.appendChild(path2);
path = document.createElementNS('http://www.w3.org/2000/svg', 'use');
path.setAttribute("xlink:href", "#conn1");
path.setAttribute("stroke", "white");
path.setAttribute("stroke-width", "7");
component.appendChild(path);
}
</script>
<style>
.dooferKasten {
background-color: rgb(82, 69, 50);
}
</style>
<body>
<div style="width:800px; height:400px; position: relative" class="dooferKasten">
<svg class="component" style="left: 0px; top: 0px; width: 800px; height: 400px; position: absolute;">
<defs><path id="conn0" d="M264 133 L396 132"></path></defs>
<use xlink:href="#conn0" stroke="black" stroke-width="9"></use>
<use xlink:href="#conn0" stroke="white" stroke-width="7"></use>
</svg>
</div>
<button onclick="test()">test</button>
<div style="width:800px; height:400px; position: relative" id="theConnections" class="dooferKasten">
</div>
</body>
</html>
Upvotes: 3
Views: 2503
Reputation: 71
Thanks to Robert Longson. That pointed in the right direction. I read an article an actually the xlink:href attribute belongs to a different Namespace. So there I had to use 'http://www.w3.org/1999/xlink' instead of 'http://www.w3.org/2000/svg'. So following the general advice to always use setAttributeNS inside my svg namespace...
and using null for non prefixed attributes...
and using the correct namespace where that attribute belongs to a whole different namespace, my code looks like that:
function test() {
component = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
component.classList.add("component");
component.style.left = '0px';
component.style.top = '0px';
component.style.width = '800px';
component.style.height = '400px';
component.style.position = "absolute";
document.getElementById("theConnections").appendChild(component);
defs = document.createElementNS('http://www.w3.org/2000/svg', 'defs');
component.appendChild(defs);
pathdef = document.createElementNS('http://www.w3.org/2000/svg', 'path');
pathdef.id = "conn1";
pathdef.setAttributeNS(null, "d", "M264 133 L396 132");
defs.appendChild(pathdef);
path2 = document.createElementNS('http://www.w3.org/2000/svg', 'use');
path2.setAttributeNS('http://www.w3.org/1999/xlink', "xlink:href", "#conn1");
path2.setAttributeNS(null, "stroke", "black");
path2.setAttributeNS(null, "stroke-width", "9");
component.appendChild(path2);
path = document.createElementNS('http://www.w3.org/2000/svg', 'use');
path.setAttributeNS('http://www.w3.org/1999/xlink', "xlink:href", "#conn1");
path.setAttributeNS(null, "stroke", "white");
path.setAttributeNS(null, "stroke-width", "7");
component.appendChild(path);
}
Upvotes: 4