如何使用d3找到在极坐标散点图上放置圆的坐标

时间:2018-02-21 15:58:54

标签: javascript d3.js

我想用d3绘制极坐标散点图,但很难将点放在正确的坐标上。我发现这是example

我在上面的示例中并不十分清楚" + Math.PI / 2"绘制径向线时的一部分。

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

&安培;这是我到目前为止所做的事情



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

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

    //Line
    var l = d3.scale.linear()
      .range([0, 360]);

    //point
    var c = d3.scale.linear()
      .range([0, 15]);



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


    var data = [
      {'Name':'A','Birth':1700, 'Point':20, 'size':120},
      {'Name':'B','Birth':1696, 'Point':45,'size':30},
      {'Name':'C','Birth':1660, 'Point':89, 'size':50},
      {'Name':'D','Birth':1784, 'Point':12, 'size':80},
      {'Name':'E','Birth':1793, 'Point':33, 'size':150},
      {'Name':'F','Birth':1750, 'Point':56, 'size':67},
      {'Name':'G','Birth':1738, 'Point':62, 'size':25},
      {'Name':'H','Birth':1813, 'Point':87, 'size':83},
      {'Name':'I','Birth':1723, 'Point':76, 'size':100},
      {'Name':'J','Birth':1786, 'Point':53, 'size':90}
    ]

      var youngest = d3.min(data, function(d) { return d.Birth; });
      var oldest = d3.max(data, function(d) { return d.Birth; });

      l.domain([Number(youngest), Number(oldest)]); 
      r.domain([0, d3.max(data, function(d) { return d.Point; })]);
      c.domain([0, d3.max(data, function(d) { return d.size; })]);

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

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

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

      gr.append("text")
        .attr("y", function(d) { return -r(d) - 4; })
        .attr("transform", "rotate(15)")
        .style("text-anchor", "middle")
        .text(function(d) { return d+'%'; });

      var ga = svg.append("g")
        .attr("class", "a axis")
        .selectAll("g")
        .data(l.ticks(12).slice(0,-1))
        .enter().append("g")
        .attr("transform", function(d) {
          return "rotate(" + (l(d)) + ")";
        });

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

        ga.append("text")
        .attr("x", radius + 6)
        .attr("dy", ".35em")
        .style("text-anchor", function(d) { return l(d) < 270 && l(d) > 90 ? "end" : null; })
        .attr("transform", function(d) { return l(d) < 270 && l(d) > 90 ? "rotate(180 " + (radius + 6) + ",0)" : null; })
        .text(function(d) { return d; });

      var color = d3.scale.category20();


      var gc = svg.append("g")
              .attr("class", "circles")

      gc.selectAll("g")
        .data(data)
        .enter()
        .append("g")
        .attr("class", "cpoint")
        .append("circle")
        .attr("class", "point")
        .attr("transform", function(d) {
          let c = [Number(d.Birth), d.Point]
          var coors = line([c]).slice(1).slice(0, -1);
          return "translate(" + coors + ")"
        })
        .attr("r", function(d){
          return c(d.size);
        })
        .attr("fill",function(d,i){
          return color(i);
        });

      gc.selectAll(".cpoint")
        .append("text")
        .attr("text-anchor", "middle")
        .attr("transform", function(d) {
          let c = [Number(d.Birth), d.Point]
          var coors = line([c]).slice(1).slice(0, -1);
          return "translate(" + coors + ")"
        })
        .text(function(d) { return d.Name + ' ' + d.Point + '%' + ' ' + d.Birth; })
        .style("font-size", '13px');
&#13;
.frame {
  fill: none;
  stroke: #000;
  }

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

  .axis line,
  .axis circle {
  fill: none;
  stroke: #777;
  stroke-dasharray: 1,4;
  }

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

  .line {
    fill: none;
    stroke: orange;
    stroke-width: 1.5px;
  }
&#13;
<script src="https://d3js.org/d3.v3.min.js"></script>
<p>Polar Scatterplot</p>
&#13;
&#13;
&#13;

不知何故,点在正确的半径(%)上,但角度(年)似乎并不合适。我也尝试使用cx和cy来放置点而不是变换,但不幸的是它返回相同的结果。

1 个答案:

答案 0 :(得分:1)

我回答了上一个问题。在你的情况下,你错过了&#34; x&#34;您向line提供的变量应该是一个角度(以弧度表示)。你给它一个&#34;年&#34;。

无论如何,在您的情况下,我的编码方式不同。这是使用一些基本三角函数的正确变换:

.attr("transform", function(d){
    // get angle and radius
    var an = l(d.Birth),
        ra = r(d.Point),
        // calc x, y position
        x = ra * Math.cos(an * Math.PI/180),
        y = ra * Math.sin(an * Math.PI/180);
    return "translate(" + [x,y] + ")";
  })

另请注意,我只需定位g并将圆圈和文字添加到其中。不,将两个元素分开放置。

运行代码:

&#13;
&#13;
<!DOCTYPE html>
<html>

<head>
  <style>
    .frame {
      fill: none;
      stroke: #000;
    }
    
    .axis text {
      font: 10px sans-serif;
    }
    
    .axis line,
    .axis circle {
      fill: none;
      stroke: #777;
      stroke-dasharray: 1, 4;
    }
    
    .axis:last-of-type circle {
      stroke: #333;
      stroke-dasharray: none;
    }
    
    .line {
      fill: none;
      stroke: orange;
      stroke-width: 1.5px;
    }
  </style>
</head>

<body>
  <script src="https://d3js.org/d3.v3.min.js"></script>
  <script>
    var width = 1200,
      height = 700,
      radius = Math.min(width, height) / 2 - 30;

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

    //Line
    var l = d3.scale.linear()
      .range([0, 360]);

    //point
    var c = d3.scale.linear()
      .range([0, 15]);



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


    var data = [{
      'Name': 'A',
      'Birth': 1700,
      'Point': 20,
      'size': 120
    }, {
      'Name': 'B',
      'Birth': 1696,
      'Point': 45,
      'size': 30
    }, {
      'Name': 'C',
      'Birth': 1660,
      'Point': 89,
      'size': 50
    }, {
      'Name': 'D',
      'Birth': 1784,
      'Point': 12,
      'size': 80
    }, {
      'Name': 'E',
      'Birth': 1793,
      'Point': 33,
      'size': 150
    }, {
      'Name': 'F',
      'Birth': 1750,
      'Point': 56,
      'size': 67
    }, {
      'Name': 'G',
      'Birth': 1738,
      'Point': 62,
      'size': 25
    }, {
      'Name': 'H',
      'Birth': 1813,
      'Point': 87,
      'size': 83
    }, {
      'Name': 'I',
      'Birth': 1723,
      'Point': 76,
      'size': 100
    }, {
      'Name': 'J',
      'Birth': 1786,
      'Point': 53,
      'size': 90
    }]

    var youngest = d3.min(data, function(d) {
      return d.Birth;
    });
    var oldest = d3.max(data, function(d) {
      return d.Birth;
    });

    l.domain([Number(youngest), Number(oldest)]);
    r.domain([0, d3.max(data, function(d) {
      return d.Point;
    })]);
    c.domain([0, d3.max(data, function(d) {
      return d.size;
    })]);

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

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

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

    gr.append("text")
      .attr("y", function(d) {
        return -r(d) - 4;
      })
      .attr("transform", "rotate(15)")
      .style("text-anchor", "middle")
      .text(function(d) {
        return d + '%';
      });

    var ga = svg.append("g")
      .attr("class", "a axis")
      .selectAll("g")
      .data(l.ticks(12).slice(0, -1))
      .enter().append("g")
      .attr("transform", function(d) {
        return "rotate(" + (l(d)) + ")";
      });

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

    ga.append("text")
      .attr("x", radius + 6)
      .attr("dy", ".35em")
      .style("text-anchor", function(d) {
        return l(d) < 270 && l(d) > 90 ? "end" : null;
      })
      .attr("transform", function(d) {
        return l(d) < 270 && l(d) > 90 ? "rotate(180 " + (radius + 6) + ",0)" : null;
      })
      .text(function(d) {
        return d;
      });

    var color = d3.scale.category20();


    var gc = svg.append("g")
      .attr("class", "circles")

    gc.selectAll("g")
      .data(data)
      .enter()
      .append("g")
      .attr("class", "cpoint")
      .attr("transform", function(d) {
        // get angle and radius
        var an = l(d.Birth),
          ra = r(d.Point),
          x = ra * Math.cos(an * Math.PI / 180),
          y = ra * Math.sin(an * Math.PI / 180);
        return "translate(" + [x, y] + ")";
      })
      .append("circle")
      .attr("class", "point")
      .attr("r", function(d) {
        return c(d.size);
      })
      .attr("fill", function(d, i) {
        return color(i);
      });

    gc.selectAll(".cpoint")
      .append("text")
      .attr("text-anchor", "middle")
      .text(function(d) {
        return d.Name + ' ' + d.Point + '%' + ' ' + d.Birth;
      })
      .style("font-size", '13px');
  </script>
</body>

</html>
&#13;
&#13;
&#13;