Creating dynamic SVG elements in JavaScript

While I was working on a HTML5 project I found this problem of creating SVG (Scalable Vector Graphics) elements
dynamically in JavaScript. For example creating vector circles inside a for loop and adding them to the page. HTML5
supports inline SVG, so you can directly use <svg>your code</svg> inside <body> to create vector graphics. But I had the task of creating them in the script. So I have put forward a small example and here is how to do it.

To create a vector circle of radius 50,

var svgNS = "http://www.w3.org/2000/svg";

var myCircle = document.createElementNS(svgNS,"circle");
myCircle.setAttributeNS(null,"id","mycircle");
myCircle.setAttributeNS(null,"cx",100);
myCircle.setAttributeNS(null,"cy",100);
myCircle.setAttributeNS(null,"r",50);
myCircle.setAttributeNS(null,"fill","black");
myCircle.setAttributeNS(null,"stroke","none");

where cx = x-coordinate of the center where you want the circle to be, similarly cy is the y-coordinate of the center.
Now that our circle is ready, we want to add it to the page, rather view it. Till now we did not add the circle to the DOM. It is important to note that SVG elements when added to our HTML page becomes a part of the DOM, so  later you can access the elements in JavaScript code and manipulate their properties.

Since html5 supports inline SVG, so write this inside your body,

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

I have used an id with the svg tag. Access the SVG tag by its id in JavaScript code and then add the circle,

document.getElementById("mySVG").appendChild(myCircle);

You should be able to see a black dark circle of radius 50 in your page at 100,100 from top left corner of the browser. Here is the full code that you can use directly,

<html>
<head>
    <title>Dynamic Vector Circle</title>
    <script type="text/javascript">
        var svgNS = "http://www.w3.org/2000/svg";  

        function createCircle()
        {
            var myCircle = document.createElementNS(svgNS,"circle"); //to create a circle, for rectangle use rectangle
            myCircle.setAttributeNS(null,"id","mycircle");
            myCircle.setAttributeNS(null,"cx",100);
            myCircle.setAttributeNS(null,"cy",100);
            myCircle.setAttributeNS(null,"r",50);
            myCircle.setAttributeNS(null,"fill","black");
            myCircle.setAttributeNS(null,"stroke","none");

            document.getElementById("mySVG").appendChild(myCircle);
        }                 

    </script>
</head>
<body onload="createCircle();">
    <svg id="mySVG" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
    </svg>
</body>
</html>

Similarly you can create other vector shapes like rectangles ,paths.
However, there is better option of doing all this. Creating dynamic vector shapes in JavaScript has been made very easy by the Raphael JavaScript library. It is very lightweight and has lots of features like charts, complex vector shapes, image crop etc.

About these ads

13 thoughts on “Creating dynamic SVG elements in JavaScript

  1. Pingback: Controlling SVG Pie Chart with a slider control « Joseph's RIA Lab

  2. Great post. I just had the same problem a googling brings me here.
    You can simplify your code just a little bit (at least for chrome) :
    - The xmlns’es can be left out of the svg element
    - You can use setAttribute instead of setAttributeNS
    Rgds,
    Georges

  3. I have problem with coordinates with dynamically add element to SVG canvas. New element act like it’s set on 0,0 coordinates but it’s displayed correctly, so when I try to attach something else to it and read coordinates I get -cx and -cy shift to its real coordinates (like it has own viewport and all drag and drop set transformation matrix starting from 0,0 coordinates (not cx, cy))

    SVGRoot = document.getElementsByTagName(“svg”)[0];
    var matrixCircle = SVGRoot.getElementById(‘mycircle’).getCTM();
    var pathLine = SVGRoot.getElementById(‘flightPath’);
    pathLine.setAttributeNS(null, ‘points’, pathLine.getAttribute(‘points’) + ” ” + matrixCircle.e + ‘,’ + matrixCircle.f);

  4. Not realy
    —-
    var svgNS = “http://www.w3.org/2000/svg”;
    var myCircle = document.createElementNS(svgNS,”circle”);
    myCircle.setAttributeNS(null,”id”,”mycircle”);
    myCircle.setAttributeNS(null,”cx”,300);
    myCircle.setAttributeNS(null,”cy”,300);
    myCircle.setAttributeNS(null,”r”,50);
    myCircle.setAttributeNS(null,”fill”,”black”);
    myCircle.setAttributeNS(null,”fill-opacity”,”0.3″);
    myCircle.setAttributeNS(null,”stroke”,”none”);
    document.getElementsByTagName(“svg”)[0].appendChild(myCircle);

    SVGRoot = document.getElementsByTagName(“svg”)[0];
    var matrixCircle = SVGRoot.getElementById(‘mycircle’).getCTM();
    alert(matrixCircle.f);
    —-
    I’ll get 0 and I would like to see 300.

  5. It looks like you need to add cx original value to translate value to get real coordinates

    var SVGRoot = document.getElementsByTagName(“svg”)[0];
    var circle = SVGRoot.getElementById(‘mycircle’);
    var matrixCircle = circle.getCTM();
    var coordinates = [parseInt(circle.getAttributeNS(null, 'cx')) + matrixCircle.e, parseInt(circle.getAttributeNS(null, 'cy')) + matrixCircle.f ];

  6. Me again :o)
    Update.
    I found some parameter named “dirty” in Raphael framework which is set to true.
    Apparently this._.dirty = true get back real coordinates on elements which are transformed, but trouble is that I dont know what does._. mean (it is some kind of object which has dirty parameter but idk who creates that object and append it to element on svg canvas)

    • Hey Z,
      I really appreciate your efforts and your comments. I have not looked into the thing yet, busy with lot of tasks. I am not sure what that ‘dirty’ thing does. I will check out.
      Thanks.

  7. Remarkable issues here. I am very satisfied tto peer your post.

    Thank you so much and I aam having a look forward to touch you.
    Will you please drop me a e-mail?

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s