Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

d3 add text to circle

I am trying to add some text into circle. I have been following example from a mbostock tutorial, but wasn't able to get the right output.

The code snippet is:

var data;
var code;

d3.json("/json/trace.json", function(json) {
  data = json;
  console.log(data);
  // get code for visualization
  code = data["code"];
  alert(code);
  var mainSVG = d3
    .select("#viz")
    .append("svg")
    .attr("width", 900)
    .attr("height", 900);
  mainSVG
    .append("circle")
    .style("stroke", "gray")
    .style("fill", "white")
    .attr("r", 100)
    .attr("cx", 300)
    .attr("cy", 300);
  circle = mainSVG.selectAll("circle").data([code]);
});

Any suggestions how to get this work?

like image 853
gizmo Avatar asked Nov 28 '12 22:11

gizmo


3 Answers

Here is an example showing some text in circles with data from a json file: http://bl.ocks.org/4474971. Which gives the following:

enter image description here

The main idea behind this is to encapsulate the text and the circle in the same "div" as you would do in html to have the logo and the name of the company in the same div in a page header.

The main code is:

var width = 960,
    height = 500;
 
var svg = d3.select("body").append("svg")
    .attr("width", width)
    .attr("height", height)
    
d3.json("data.json", function(json) {
    /* Define the data for the circles */
    var elem = svg.selectAll("g")
        .data(json.nodes)
  
    /*Create and place the "blocks" containing the circle and the text */  
    var elemEnter = elem.enter()
        .append("g")
        .attr("transform", function(d){return "translate("+d.x+",80)"})
 
    /*Create the circle for each block */
    var circle = elemEnter.append("circle")
        .attr("r", function(d){return d.r} )
        .attr("stroke","black")
        .attr("fill", "white")
 
    /* Create the text for each block */
    elemEnter.append("text")
        .attr("dx", function(d){return -20})
        .text(function(d){return d.label})
})

and the json file is:

{"nodes":[
  {"x":80, "r":40, "label":"Node 1"}, 
  {"x":200, "r":60, "label":"Node 2"}, 
  {"x":380, "r":80, "label":"Node 3"}
]}

The resulting html code shows the encapsulation you want:

<svg width="960" height="500">
    <g transform="translate(80,80)">
        <circle r="40" stroke="black" fill="white"></circle>
        <text dx="-20">Node 1</text>
    </g>
    <g transform="translate(200,80)">
        <circle r="60" stroke="black" fill="white"></circle>
        <text dx="-20">Node 2</text>
    </g>
    <g transform="translate(380,80)">
        <circle r="80" stroke="black" fill="white"></circle>
        <text dx="-20">Node 3</text>
    </g>
</svg>

jsfiddle with working code: http://jsfiddle.net/chrisJamesC/DY7r4/

like image 84
Christopher Chiche Avatar answered Nov 16 '22 18:11

Christopher Chiche


Extended the example above to fit the actual requirements, where circled is filled with solid background color, then with striped pattern & after that text node is placed on the center of the circle.

var width = 960,
  height = 500,
  json = {
    "nodes": [{
      "x": 100,
      "r": 20,
      "label": "Node 1",
      "color": "red"
    }, {
      "x": 200,
      "r": 25,
      "label": "Node 2",
      "color": "blue"
    }, {
      "x": 300,
      "r": 30,
      "label": "Node 3",
      "color": "green"
    }]
  };

var svg = d3.select("body").append("svg")
  .attr("width", width)
  .attr("height", height)

svg.append("defs")
  .append("pattern")
  .attr({
    "id": "stripes",
    "width": "8",
    "height": "8",
    "fill": "red",
    "patternUnits": "userSpaceOnUse",
    "patternTransform": "rotate(60)"
  })
  .append("rect")
  .attr({
    "width": "4",
    "height": "8",
    "transform": "translate(0,0)",
    "fill": "grey"
  });

function plotChart(json) {
  /* Define the data for the circles */
  var elem = svg.selectAll("g myCircleText")
    .data(json.nodes)

  /*Create and place the "blocks" containing the circle and the text */
  var elemEnter = elem.enter()
    .append("g")
    .attr("class", "node-group")
    .attr("transform", function(d) {
      return "translate(" + d.x + ",80)"
    })

  /*Create the circle for each block */
  var circleInner = elemEnter.append("circle")
    .attr("r", function(d) {
      return d.r
    })
    .attr("stroke", function(d) {
      return d.color;
    })
    .attr("fill", function(d) {
      return d.color;
    });

  var circleOuter = elemEnter.append("circle")
    .attr("r", function(d) {
      return d.r
    })
    .attr("stroke", function(d) {
      return d.color;
    })
    .attr("fill", "url(#stripes)");

  /* Create the text for each block */
  elemEnter.append("text")
    .text(function(d) {
      return d.label
    })
    .attr({
      "text-anchor": "middle",
      "font-size": function(d) {
        return d.r / ((d.r * 10) / 100);
      },
      "dy": function(d) {
        return d.r / ((d.r * 25) / 100);
      }
    });
};

plotChart(json);
.node-group {
  fill: #ffffff;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>

Output:

enter image description here

Below is the link to codepen also:

See the Pen D3-Circle-Pattern-Text by Manish Kumar (@mkdudeja) on CodePen.

Thanks, Manish Kumar

like image 30
Manish Kumar Avatar answered Nov 16 '22 17:11

Manish Kumar


Here's a way that I consider easier: The general idea is that you want to append a text element to a circle element then play around with its "dx" and "dy" attributes until you position the text at the point in the circle that you like. In my example, I used a negative number for the dx since I wanted to have text start towards the left of the centre.

const nodes = [ {id: ABC, group: 1, level: 1}, {id:XYZ, group: 2, level: 1}, ]

const nodeElems = svg.append('g')
.selectAll('circle')
.data(nodes)
.enter().append('circle')
.attr('r',radius)
.attr('fill', getNodeColor)

const textElems = svg.append('g')
.selectAll('text')
.data(nodes)
.enter().append('text')
.text(node => node.label)
.attr('font-size',8)//font size
.attr('dx', -10)//positions text towards the left of the center of the circle
.attr('dy',4)
like image 4
Kenaa Avatar answered Nov 16 '22 19:11

Kenaa