D3 – add labels to polar plot

I’d just create a dummy data structure, with the key being the name, and the value being the angle I want it at. Then use some basic trigonometry to position the nodes correctly.

var width = 960,
  height = 500,
  radius = Math.min(width, height) / 2 - 30;

var r = d3.scale.linear()
  .domain([0, 1])
  .range([0, radius]);

var line = d3.svg.line.radial()
  .radius(function(d) {
    return r(d[1]);
  })
  .angle(function(d) {
    return -d[0] + Math.PI / 2;
  });

var svg = d3.select("body").append("svg")
  .attr("width", width)
  .attr("height", height)
  .append("g")
  .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");

var gr = svg.append("g")
  .attr("class", "r axis")
  .selectAll("g")
  .data(r.ticks(3).slice(1))
  .enter().append("g");

gr.append("circle")
  .attr("r", r);

var ga = svg.append("g")
  .attr("class", "a axis")
  .selectAll("g")
  .data(d3.range(0, 360, 30))
  .enter().append("g")
  .attr("transform", function(d) {
    return "rotate(" + -d + ")";
  });

ga.append("line")
  .attr("x2", radius);

var color = d3.scale.category20();

var line = d3.svg.line.radial()
  .radius(function(d) {
    return r(d[1]);
  })
  .angle(function(d) {
    return -d[0] + Math.PI / 2;
  });

var data = [
  [Math.PI / 3, Math.random()],
  [Math.PI / 6, Math.random()],
  [0 * Math.PI, Math.random()],
  [(11 * Math.PI) / 6, Math.random()],
  [(5 * Math.PI / 3), Math.random()],
  [(3 * Math.PI) / 2, Math.random()],
  [(4 * Math.PI / 3), Math.random()],
  [(7 * Math.PI) / 6, Math.random()],
  [Math.PI, Math.random()],
  [(5 * Math.PI) / 6, Math.random()],
  [(2 * Math.PI) / 3, Math.random()],
  [Math.PI / 2, Math.random()]
];

var angles = {
  N: 0,
  E: Math.PI / 2,
  S: Math.PI,
  W: 3 * Math.PI / 2,
};

svg.selectAll("point")
  .data(data)
  .enter()
  .append("circle")
  .attr("class", "point")
  .attr("transform", function(d) {
    var coors = line([d]).slice(1).slice(0, -1);
    return "translate(" + coors + ")"
  })
  .attr("r", 8)
  .attr("fill", function(d, i) {
    return color(i);
  });

svg.selectAll(".angle")
  .data(Object.keys(angles))
  .enter()
  .append("text")
  .attr("class", "angle")
  .attr("text-anchor", "middle")
  .attr("dominant-baseline", "middle")
  .attr("transform", function(d) {
    // Subtract because 0degrees is up at (0, 1) on the unit circle, but
    // 0 radians is to the right, at (1, 0)
    var angle = angles[d] - Math.PI / 2;
    var textRadius = radius + 20;
    var x = Math.cos(angle) * textRadius;
    var y = Math.sin(angle) * textRadius;
    return "translate(" + [x, y] + ")";
  })
  .text(function(d) { return d; })
.frame {
  fill: none;
  stroke: #000;
}

.axis text {
  font: 10px sans-serif;
}

.axis line,
.axis circle {
  fill: none;
  stroke: steelblue;
  stroke-dasharray: 4;
}

.axis:last-of-type circle {
  stroke: steelblue;
  stroke-dasharray: none;
}

.line {
  fill: none;
  stroke: orange;
  stroke-width: 3px;
}
<script src="//d3js.org/d3.v3.min.js"></script>

CLICK HERE to find out more related problems solutions.

Leave a Comment

Your email address will not be published.

Scroll to Top