Rasyq
Rasyq

Reputation: 45

How to display data map in D3 svg rectangle?

I'm trying to display key-value pair data inside SVG rectangle using D3. For that purpose the data is read in map. I'm able to display first K-V inside the rectangle. Here is code:

data = {"Key1": 4,
    "Key2": "Value2",
    "Key3": "BFA",
    "Key4": "Applied",
    "level": "Upper",
    "description": "To test this category",
    };
var mymap = d3.map(data);
var drect = d3.selectAll("body").append("svg").attr("width", "100%").attr("height", "100%").append("g");
var drect_rect = drect.append("rect")
                        .attr("width",200)
                        .attr("height",300)
                        .attr("x",100)
                        .attr("y",200)
                        .attr("stroke-width","1px")
                        .attr("stroke","#a8a8a8")
                        .attr("fill","none");               
var drect_text = drect.append("text")
                        .attr("x",110)
                        .attr("y",210)
                        .style("fill", "black")
                        .text(function(d){
                            //mymap.forEach(function(k,v){console.log(k,v);});
                            return mymap.keys()[0] +":"+ mymap.values()[0];
                            });

Having done that, I thought why not iterate on map entries and append text of each K-V pair? so I tried following code. But it fails because there is no iterator i to catch hold of.

mymap.forEach(function(k,v,i){
        drect.append("text")
                        .attr("x",110)
                        .attr("y",function(i){return 210+(i*20);})
                        .style("fill", "black")
                        .text(function(i){
                            return mymap.keys()[i] +":"+ mymap.values()[i];
                            }); 
                    });

I doubt I'm on right path. I'm trying to achieve following text output in SVG rectangle and open to any other library like D3+ or jQuery. Still facing problem in basic D3 lib.

Key1: 4
Key2: Value2
Key3: BFA
Key4: Applied
level: Upper
description: To test this category

Upvotes: 1

Views: 528

Answers (1)

Mark
Mark

Reputation: 108512

You should take advantage of d3 data-binding. In order for it to work, you have to "d3-ify" your data and move it from an object to an array. d3.entries will work well for this:

var d3_data = d3.entries(data); //<-- convert data to array

drect.selectAll('text')
  .data(d3_data) //<-- data-binding
  .enter()
  .append("text") //<-- append text for every entry in array
  .attr("x", 110)
  .attr("y", function(d,i){
    return 210 + (i * 20); //<-- position it on y
  })
  .style("fill", "black")
  .text(function(d) {
    return d.key + ": " + d.value; //<-- add text
  });

Full code:

<!DOCTYPE html>
<html>

<head>
  <script data-require="[email protected]" data-semver="3.5.3" src="//cdnjs.cloudflare.com/ajax/libs/d3/3.5.3/d3.js"></script>
</head>

<body>
  <script>
    var data = {
      "Key1": 4,
      "Key2": "Value2",
      "Key3": "BFA",
      "Key4": "Applied",
      "level": "Upper",
      "description": "To test this category",
    };
    
    var mymap = d3.map(data);
    var drect = d3.selectAll("body")
      .append("svg")
      .attr("width", "100%")
      .attr("height", "500px")
      .append("g");

    var drect_rect = drect.append("rect")
      .attr("width", 250)
      .attr("height", 300)
      .attr("x", 100)
      .attr("y", 20)
      .attr("stroke-width", "1px")
      .attr("stroke", "#a8a8a8")
      .attr("fill", "none");
      
    var d3_data = d3.entries(data);
      
    drect.selectAll('text')
      .data(d3_data)
      .enter()
      .append("text")
      .attr("x", 110)
      .attr("y", function(d,i){
        return 40 + (i * 20);
      })
      .style("fill", "black")
      .text(function(d) {
        return d.key + ": " + d.value;
      });
  </script>
</body>

</html>

Upvotes: 1

Related Questions