block by nitaku af6f61a8de5888b8e035

Radar chart

Full Screen

-

index.js

/* polar layout
*/


(function() {
  var RADIUS, csv, data, height, max, outer_polygon_generator, polar, polar_data, polar_layout, polygon_generator, svg, width;

  polar = function() {
    var self;

    self = function(data) {
      data.forEach(function(d, i) {
        return d.angle = i * 2 * Math.PI / data.length;
      });
      return data;
    };
    return self;
  };

  /* ---
  */


  csv = 'category,value\none,323\ntwo,534\nthree,230\nfour,156\nfive,336';

  data = d3.csv.parse(csv);

  data.forEach(function(d) {
    return d.value = +d.value;
  });

  max = d3.max(data, function(d) {
    return d.value;
  });

  width = 960;

  height = 500;

  RADIUS = Math.min(width, height) / 2 - 40;

  polar_layout = polar();

  polar_data = polar_layout(data);

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

  polygon_generator = d3.svg.line().x(function(d) {
    return RADIUS / max * d.value * Math.cos(d.angle);
  }).y(function(d) {
    return RADIUS / max * d.value * Math.sin(d.angle);
  });

  svg.append("path").datum(polar_data).attr({
    "class": 'polygon',
    d: function(ds) {
      return polygon_generator(ds) + 'z';
    }
  });

  outer_polygon_generator = d3.svg.line().x(function(d) {
    return RADIUS * Math.cos(d.angle);
  }).y(function(d) {
    return RADIUS * Math.sin(d.angle);
  });

  svg.append("path").datum(polar_data).attr({
    "class": 'outer_polygon',
    d: function(ds) {
      return outer_polygon_generator(ds) + 'z';
    }
  });

  svg.selectAll(".radius").data(polar_data).enter().append("path").attr('class', 'radius').attr("d", function(d) {
    return "M0 0 L" + (RADIUS * Math.cos(d.angle)) + " " + (RADIUS * Math.sin(d.angle));
  });

  svg.selectAll(".dot").data(polar_data).enter().append("circle").attr('class', 'dot').attr({
    cx: function(d) {
      return "" + (RADIUS / max * d.value * Math.cos(d.angle));
    },
    cy: function(d) {
      return "" + (RADIUS / max * d.value * Math.sin(d.angle));
    },
    r: 3
  });

}).call(this);

index.html

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="description" content="Radar chart" />
  <title>Radar chart</title>
  <link rel="stylesheet" href="index.css">
  <script src="//d3js.org/d3.v3.min.js"></script>
</head>
<body>
  <script src="index.js"></script>
</body>
</html>

index.coffee

### polar layout ###
polar = () ->
  # defaults
  #scale = d3.scale.linear
  
  self = (data) ->
    data.forEach (d, i) ->
      d.angle = i * 2*Math.PI/data.length
      
    return data
  
  return self
    
### --- ###

csv = '''
category,value
one,323
two,534
three,230
four,156
five,336
'''

data = d3.csv.parse csv
data.forEach (d) ->  d.value = +d.value

max = d3.max(data, (d) -> d.value)

width = 960
height = 500
RADIUS = Math.min(width, height) / 2 - 40


polar_layout = polar()
polar_data = polar_layout(data)

svg = d3.select("body").append("svg")
    .attr("width", width)
    .attr("height", height)
  .append("g")
    .attr
      transform: "translate(#{width/2}, #{height/2})"

      
polygon_generator = d3.svg.line()
  .x((d) -> RADIUS/max*d.value*Math.cos(d.angle))
  .y((d) -> RADIUS/max*d.value*Math.sin(d.angle))

svg.append("path")
  .datum(polar_data)
    .attr
      class: 'polygon'
      d: (ds) -> polygon_generator(ds) + 'z'
      
      
outer_polygon_generator = d3.svg.line()
  .x((d) -> RADIUS*Math.cos(d.angle))
  .y((d) -> RADIUS*Math.sin(d.angle))

svg.append("path")
  .datum(polar_data)
    .attr
      class: 'outer_polygon'
      d: (ds) -> outer_polygon_generator(ds) + 'z'
      
svg.selectAll(".radius")
    .data(polar_data)
  .enter().append("path")
    .attr('class','radius')
    .attr("d", (d) -> "M0 0 L#{RADIUS*Math.cos(d.angle)} #{RADIUS*Math.sin(d.angle)}")
    
svg.selectAll(".dot")
    .data(polar_data)
  .enter().append("circle")
    .attr('class','dot')
    .attr
      cx: (d) -> "#{RADIUS/max*d.value*Math.cos(d.angle)}"
      cy: (d) -> "#{RADIUS/max*d.value*Math.sin(d.angle)}"
      r: 3

index.css

svg {
  background-color: white;
}
.radius {
  stroke: gray;
  stroke-dasharray: 3 3;
}
.polygon {
  fill: orange;
  fill-opacity: 0.2;
  stroke: orange;
}
.outer_polygon {
  fill: none;
  stroke: gray;
  stroke-dasharray: 3 3;
}