tonyf tonyf - 7 months ago 11
HTML Question

Constructing an Inline SVG Diagram using Javasctipt with JSON

I'm currently working on a project that involves building a dynamic diagram and am looking at using SVGs for this.

Based on this, was looking at getting some assistance with the following queries please and to see also, whether what I am after is actually possible with SVGs.

1) Using javascript and json,is it possible to build an SVG diagram within a HTML page dynamically, based on my json data?

Basically, I want to construct say a rectangle box within the page, where I can have say 1 to 10 svg lines as inputs into the rectangle box, on the left hand side. To determine how many actual lines appear, will come from my json object.

So as mentioned above, is this possible and if so, how might this be setup to draw this inline svg diagram?

2) Again, using javascript, is it possible to place hyperlink labels on these svg lines, again based on info within the json object?

I started playing with static inline SVG but unsure how to construct this using javascript instead, to cover off my two points above, i.e.:

<body>
<h1>My SVG Test</h1><hr/>

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

<text x="465" y="90" fill="red">Heading One</text>
<image x="100" y="110" width="50%" height="50%"
xlink:href="http://my-image.com/myimg.jpg" />

<line x1="25" y1="80" x2="350" y2="80" style="stroke: #000000; stroke-width: 2;"/>
</svg>

</body>


Thanks.

Answer

You can use Snap to easily create what you are looking for. In the below snippet,I added all the required attributes and type of the element and used .el() to create an svg element

The syntax for el is

Paper.el(name,attr)

Name is the element that you want to create, for example line,circle,path etc and attr is the attributes that you want to add. In the data below i have created two lines and one circle by specifying their attributes . I have also added fill and stroke

var data = [
{
  type:"line",
  attrs:{
    x1:0,
    x2:0,
    y1:0,
    y2:100,
    stroke:"black",
    "stroke-width":"5"
  }
},
{
  type:"line",
  attrs:{
    x1:100,
    x2:100,
    y1:0,
    y2:100,
    stroke:"black",
    "stroke-width":"5"
  }
},
{
  type:"circle",
  attrs:{
    cx:50,
    cy:50,
    r:40,
    fill:"orange", 
  }
} 
]
var s = Snap("svg");
for(var x=0;x<data.length;x++){
  s.el(data[x].type).attr(data[x].attrs);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/snap.svg/0.3.0/snap.svg-min.js"></script>
<svg width="500" height="500" viewbox="0 0 100 100"></svg>

Adding a link is a bit hard and complex because you have to append a child text element to the a. So i have changed my code a bit.

In the following snippet i have added a new key to the json data called parent. And then set parent:true to those elements who have child elements and run another loop to append the child element to the parent

var data = [{
  type: "line",
  parent: false, //is false because it has no child elements
  attrs: {
    x1: 0,
    x2: 0,
    y1: 0,
    y2: 100,
    stroke: "black",
    "stroke-width": "5"
  }
}, {
  type: "line",
  parent: false,
  attrs: {
    x1: 100,
    x2: 100,
    y1: 0,
    y2: 100,
    stroke: "black",
    "stroke-width": "5"
  }
}, {
  type: "circle",
  parent: false,
  attrs: {
    cx: 50,
    cy: 50,
    r: 40,
    fill: "orange",
  }
}, {
  type: "a",
  parent: true, // Is true because this has child elements
  attrs: {
    x: 10,
    y: 50,
    "xlink:href": "http://snapsvg.io/docs/"
  },
  childs: [{
    type: "text",
    attrs: {
      x: 10,
      y: 50,
      text: "Snap is Cool",
    }
  }]
}, {
  type: "image",
  parent: false,
  attrs: {
    "xlink:href": "http://i.imgur.com/5NK0H1e.jpg",
    x: 0,
    y: 0,
    width: 50,
    height: 50
  }
}]
var s = Snap("svg");
for (var x = 0; x < data.length; x++) {
  var p = s.el(data[x].type).attr(data[x].attrs);
  if (data[x].parent) { //check if it is true
    for (var y = 0; y < data[x].childs.length; y++) {
      var c = s.el(data[x].childs[y].type).attr(data[x].childs[y].attrs);
      p.append(c);
    }
  }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/snap.svg/0.3.0/snap.svg-min.js?wmode=transparent"></script>
<svg width="500" height="500" viewbox="0 0 100 100"></svg>

To add more child elements the following code should be used

var data = [{
  type: "g"
}, {
  type: "image",
  appendTo: 0,
  attrs: {
    "xlink:href": "http://lorempixel.com/500/500/",
    x: 0,
    y: 0,
    width: 50,
    height: 50
  }
}, {
  appendTo: 0,
  type: "a",
  parent: true,
  attrs: {
    x: 5,
    y: 5,
    target: "_blank",
    "xlink:href": "http://snapsvg.io/docs/"
  }
}, {
  appendTo: 2,
  type: "circle",
  attrs: {
    cx: 5,
    cy: 5,
    r: 2.5,
    fill: "orange"
  }
}]
var s = Snap("svg");
var elems = [];
for (var x = 0; x < data.length; x++) {
  var e = s.el(data[x].type).attr(data[x].attrs);
  if (data[x]["appendTo"] !== undefined) {
    var p = elems[data[x].appendTo];
    p.append(e);
  }
  elems.push(e);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/snap.svg/0.3.0/snap.svg-min.js"></script>
<div class="box">
  <svg width="100%" height="100%" viewBox="0 0 100 100"></svg>
</div>

Comments