0_0
0_0

Reputation: 209

Insert items into SVG elements dynamically

I've been experimenting with SVG, and wanted to insert elements into the SVG elements dynamically according to the data that I get.

So say, in the data, I have 2 rows, and 5 columns in each row.
I need to draw 10 (2*5) items in the SVG element (rect, polygon, etc).
eg : the # represent svg element boundries.

###########             #######
#1 2 3 4 5#            #12345#
#1 2 3 4 5#           #12345#
###########          #######
  rect               polygon

I could solve the rect, but however, cannot seem to understand how to go about the other shapes.

Could you please help in how to solve this. Thanks.

Note : It is ok, if using some library can help, please recommend, since I don't know if it is even possible using existing libraries.

Here is a fiddle for this. Below is the code for filling elements in rect:

SVG :

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
   xmlns:dc="http://purl.org/dc/elements/1.1/"
   xmlns:cc="http://creativecommons.org/ns#"
   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
   xmlns:svg="http://www.w3.org/2000/svg"
   xmlns="http://www.w3.org/2000/svg"
   version="1.1"
   width="138.64612"
   height="214.38011"
   id="svg4796">
  <defs
     id="defs4798" />
  <metadata
     id="metadata4801">
    <rdf:RDF>
      <cc:Work
         rdf:about="">
        <dc:format>image/svg+xml</dc:format>
        <dc:type
           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
        <dc:title></dc:title>
      </cc:Work>
    </rdf:RDF>
  </metadata>
  <g
     transform="translate(-132.1123,-309.24939)"
     id="layer1">
    <rect
       class="fill_me"
       width="135.72713"
       height="87.295868"
       x="134.5313"
       y="309.74939"
       id="rect5355"
       style="fill:#040404;fill-opacity:1;stroke:#ffffff;stroke-opacity:1" />
    <polygon
       class="fill_me"
       style="fill:#040404;fill-opacity:1;stroke:#848484;stroke-width:0.75"
       transform="matrix(0.939298,0,0,0.90867846,28.384527,198.27875)"
       id="cat_0000000051"
       points="148.2,240.301 133.1,273.6     110.8,325.334 228.133,357.667 239.899,269 148.2,240.301  " />
  </g>
</svg>

JavaScript :

// Get the required elements, and the attributes for the item to be filled.
var svg = document.querySelectorAll('svg')[0];
var block = svg.getElementsByClassName('fill_me')[0];
var b = {
    width : Math.floor(block.getBBox().width),
    height : Math.floor(block.getBBox().height),
    posX : Math.floor(block.getBoundingClientRect().left),
    posY : Math.floor(block.getBoundingClientRect().top)
};

var drawShape = function (tag, attrs) {
    var el = document.createElementNS('http://www.w3.org/2000/svg', tag);
    for (var i in attrs)
        el.setAttribute(i, attrs[i]);

    return el;
};

// This will create a group in which the items will be filled.
var grp = drawShape('g');
svg.appendChild(grp);

// this is the data, according to which the block needs to be filled.
var items = ['xava|xav2|xav3|xav4|xav5|xav6|xav7|xav8|xav9|xaav|xaaa|xaa2|xaa3|x2a4', 'xvvv|x2v2|xav3|xav4|xav5|xav6|xav7|xav8|xav9|xaav|xaaa|xaa2|xaa3|xaa4', 'xvvv|xvvv|xav3|xav4|xav5|xav6|xav7|xav8|x2v9|x2av|x2aa|x2a2|x2a3|x2a4', 'xvvv|xvvv|x2v3|x2v4|x2v5|x2v6|xav7|xav8|xav9|xaav|xaaa|xaa2|xaa3|xaa4', 'xvvv|xvvv|xvvv|x2v4|x2v5|xav6|xav7|xav8|xav9|xaav|xaaa|xaa2|xaa3|xaa4', 'xvvv|xvvv|xvvv|xvvv|x2v5|xav6|xav7|xav8|xav9|xaav|xaaa|xaa2|xaa3|xaa4', 'xvvv|xvvv|xvvv|xvvv|xvvv|x2v6|xav7|xav8|xav9|xaav|xaaa|xaa2|xaa3|xaa4', 'xvvv|xvvv|xvvv|xvvv|xvvv|xvvv|xav7|xav8|xav9|xaav|xaaa|xaa2|xaa3|xaa4', 'xvvv|xvvv|xvvv|xvvv|xvvv|xvvv|xav7|xav8|xav9|xaav|xaaa|xaa2|xaa3|xaa4', 'xvvv|xvvv|xvvv|xvvv|xvvv|xvvv|xvvv|x2v8|x2v9|x2av|xaaa|xaa2|xaa3|xaa4'];

var rowSize = items[0].split('|').length;   // pick the first one, since all of them have the same length
var colSize = items.length;

var itemSize = {
    width : Math.floor(b.width / rowSize),
    height : Math.floor(b.height / colSize)
};

// For each row!
for (var i = 0; i < colSize; i++) {
    var fil = items[i].split('|');

    // For each column within row
    for (var j = 0; j < fil.length; j++) {
        var draw = drawShape('circle', {
            r: itemSize.width/3,
            cx: b.posX + j * itemSize.width + itemSize.width/2,
            cy: b.posY + i * itemSize.height + itemSize.height/2
        });

        if (j === 0 || fil[j] === 'x2v5' || fil[j] === 'x2v9')
            continue;

        grp.appendChild(draw);
    }
}

Upvotes: 3

Views: 560

Answers (1)

John Kiernander
John Kiernander

Reputation: 4904

Inserting SVG elements based on data is exactly what d3js was built for. If you want to draw charts there are lots of libraries based on d3 which make life easier. My favourite is dimple but I suppose I'm a bit biased...

Upvotes: 1

Related Questions