OiO.lk Blog HTML Issue with dynamic SVG rendering from JavaScript
HTML

Issue with dynamic SVG rendering from JavaScript


I am foraying back into the world of web development, so there is a good chance that this is something silly I have overlooked.

I have been able to dynamically create all the HTML components for the SVG I am trying to create, however the resulting image isn’t displayed in it’s container. My aim is to create an SVG element with a random number of circles, this needs to be repeatable so that I can display more than one on the page at a time.

This is an example of what my code outputs:

<svg class="canvas" id="gen1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1000 1000">
 <filter id="shadow">
   <feDropShadow dx="0" dy="10" stdDeviation="2" flood-opacity="0.4"></feDropShadow> 
 </filter>
 <radialGradient id="highlight" cx="50%" cy="50%" r="50%" fx="50%" fy="25%">
  <stop offset="0%" stop-color="#FF4D4D"></stop>
  <stop offset="100%" stop-color="#8B0000"></stop>
 </radialGradient>
 <circle id="circle1" cx="500" cy="166.66666666666666" r="83.33333333333333" fill="url(#highlight)" filter="url(#shadow)"></circle>
 <circle id="circle2" cx="500" cy="666.6666666666666" r="83.33333333333333" fill="url(#highlight)" filter="url(#shadow)"></circle>
 <circle id="circle3" cx="166.6666666666669" cy="744.0169358562925" r="83.33333333333333" fill="url(#highlight)" filter="url(#shadow)"></circle>
 <circle id="circle4" cx="750.0000000000001" cy="599.6793685588859" r="83.33333333333333" fill="url(#highlight)" filter="url(#shadow)"></circle>
</svg>

If I take the above code and paste it into an online SVG viewer the output is exactly what I expect it to be. However inside the basic page I have built it doesn’t show any of the circles, even though when I inspect the HTML I can see all these elements there.

This is the code I am using to generate the SVG:

function buildCanvas(canvasNumber) {
    let canvas = buildNode(new Node("div", [new Attribute("class", "canvas"), new Attribute("id", "gen" + canvasNumber)], undefined, [
        new Node("h1", [new Attribute("class", "canvasTitle"), new Attribute("id", "canvas" + canvasNumber + "Title")], "Canvas " + canvasNumber),
        new Node("svg", [new Attribute("ns", "http://www.w3.org/2000/svg"), new Attribute("class", "canvas"), new Attribute("id", "canvas" + canvasNumber + "Layout"), new Attribute("xmlns", "http://www.w3.org/2000/svg"), new Attribute("viewBox", "0 0 1000 1000")], undefined,  [
            new Node("filter", [new Attribute("ns", "http://www.w3.org/2000/svg"), new Attribute("id", "shadow")], undefined, [
                new Node("feDropShadow", [new Attribute("ns", "http://www.w3.org/2000/svg"), new Attribute("dx", "0"), new Attribute("dy", "10"), new Attribute("stdDeviation", "2"), new Attribute("flood-opacity", "0.4")])
            ]),
            new Node("radialGradient",  [new Attribute("ns", "http://www.w3.org/2000/svg"), new Attribute("id", "highlight"), new Attribute("cx", "50%"), new Attribute("cy", "50%"), new Attribute("r", "50%"), new Attribute("fx", "50%"), new Attribute("fy", "25%")], undefined, [
                new Node("stop", [new Attribute("ns", "http://www.w3.org/2000/svg"), new Attribute("offset", "0%"), new Attribute("stop-color", "#FF4D4D")]),
                new Node("stop", [new Attribute("ns", "http://www.w3.org/2000/svg"), new Attribute("offset", "100%"), new Attribute("stop-color", "#8B0000")])
            ])
        ].concat(drawHole(canvases[canvasNumber - 1]))),
        new Node("h3", [new Attribute("class", "canvasTarget"), new Attribute("id", "canvas" + canvasNumber + "Target")], "Target " + canvases[canvasNumber - 1].target),
        new Node("div", [new Attribute("class", "canvasScores"), new Attribute("id", "canvas" + canvasNumber + "Scores")])
    ]));
    return canvas;
}

function drawHole(canvas) {
    const circlePositions = canvas.circles;
    let circleNum = 1;
    let circles = [];
    circlePositions.forEach(circle => {
        circles.push(new Node("circle", [
            new Attribute("ns", "http://www.w3.org/2000/svg"),
            new Attribute("id", "circle" + circleNum),
            new Attribute("cx", ball.x),
            new Attribute("cy", ball.y),
            new Attribute("r", 1000/12),
            new Attribute("fill", "url(#highlight)"),
            new Attribute("filter", "url(#shadow)")]))
        circleNum++;
    });

    return balls;
}

function buildNode(node = new Node("div")) {
    let nodeComp = document.createElement(node.type);
    if (node.attributes != null && typeof node.attributes !== "undefined" && node.attributes.length > 0) {
        let ns;
        for (let position = 0; position < node.attributes.length; position++) {
            if (node.attributes[position].type == "ns") {
                ns = node.attributes[position].value;
                nodeComp = document.createElementNS(ns, node.type);
                continue;
            }
            if (ns != null && typeof ns !== "undefined") {
                try {
                    nodeComp.setAttributeNS(ns, node.attributes[position].type, node.attributes[position].value);
                    continue;
                }
                catch (err) {

                }
            }
            let attribute = document.createAttribute(node.attributes[position].type);
            attribute.value = node.attributes[position].value;
            nodeComp.setAttributeNode(attribute);
        }
    }
    if (node.content != null && typeof node.content !== "undefined") {
        nodeComp.innerHTML = node.content;
    }
    if (node.childNodes != null && typeof node.childNodes !== "undefined" && node.childNodes.length > 0) {
        for (let childNode = 0; childNode < node.childNodes.length; childNode++) {
            nodeComp.insertAdjacentElement("beforeend", buildNode(node.childNodes[childNode]));
        }
    }
    return nodeComp;
}

If anyone can spot my mistake or niggle to make the circles display on the canvas please put me out of my misery.



You need to sign in to view this answers

Exit mobile version