d3.js 繪制極坐標圖(polar plot)


0.引言

在極坐標系中,任意位置可由一個夾角和一段相對原點(極點)的距離表示。也就是說,我們可以用 (angle,r) 來表示極坐標系中的點。

 

1.數據

假設我們有如下數據集[ [10, 0.2], [6, 0.5], [23, 0.9],... ]。其中每個數據的一維表示時間(24小時制),二維表示信號強度。如[10, 0.2]表示十點的信號強度為0.2。現在,我們要將這些數據呈現在極坐標圖(polar plot)上:

 

2.比例尺

我們發現,源數據的一維並不直接表示角度,二維也並不直接表示距離。那么我們需要用到比例尺。比例尺就是將某一區域的值映射到另一區域,其大小關系不變。

由於我們的區間都是連續的(連續的24小時映射到連續的360°,信號強度值映射到半徑值),故這里我們用到的是線性比例尺。

1 var angle = d3.scale.linear()
2               .domain([0, 24])
3               .range([0, 2 * Math.PI]);
4 
5 var r = d3.scale.linear()
6           .domain([0, max_singnal])
7           .range([0, radius]);

 

 

3.坐標系

為了清晰地呈現數據,繪制角度坐標軸(每45°畫一條線)和半徑坐標軸(半徑每遞增0.1畫一個圓)。以及標上刻度。

// 角度坐標軸
1
var ga = svg.append("g") 2 .attr("class", "a axis") 3 .selectAll("g") 4 .data(d3.range(-90, 270, 45)) 5 .enter().append("g") 6 .attr("transform", function(d) { 7 return "rotate(" + d + ")"; 8 }); 9 10 ga.append("line") 11 .attr("x2", radius); 12 13 ga.append("text") 14 .attr("x", radius + 6) 15 .attr("dy", ".35em") 16 .style("text-anchor", function(d) { return d < 270 && d > 90 ? "end" : null; }) 17 .attr("transform", function(d) { 18 return d < 270 && d > 90 ? "rotate(180 " + (radius + 6) + ",0)" : null; 19 }) 20 .text(function(d,i) { return i*3 + ":00" });
// 半徑坐標軸
1
var gr = svg.append("g") 2 .attr("class", "r axis") 3 .selectAll("g") 4 .data(r.ticks(max_singnal*10).slice(1)) 5 .enter().append("g"); 6 7 gr.append("circle") 8 .attr("r", r); 9 10 gr.append("text") 11 .attr("y", function(d) { return -r(d) - 4; }) 12 .attr("transform", "rotate(20)") 13 .style("text-anchor", "middle") 14 .text(function(d) { return d; });

 

 

4.繪制數據點

 1     var color = d3.scale.category20();
 2 
 3     var line = d3.svg.line.radial()
 4           .angle(function(d) {
 5             return angle(d[0]);
 6           })
 7           .radius(function(d) {
 8             return r(d[1]);
 9           });
10       
11 
12     svg.selectAll("point")
13           .data(data)
14           .enter()
15           .append("circle")
16           .attr("class", "point")
17           .attr("transform", function(d) {
18             var coors = line([d]).slice(1).slice(0, -1);
19             return "translate(" + coors + ")"
20           })
21           .attr("r", 8)
22           .attr("fill",function(d,i){
23             return color(i);
24           });

 

 

5.完整代碼

 

<!DOCTYPE html>
<meta charset="utf-8">
<style>
  .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;
  }
</style>

<body>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.17/d3.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
  <script>
      var width = 960,
          height = 500,
          radius = Math.min(width, height) / 2 - 30;
    
    var data = [
      [0, 0.4],
      [6, 0.2],
      [Math.random()*24, Math.random()],
      [Math.random()*24, Math.random()],
      [Math.random()*24, Math.random()],
      [Math.random()*24, Math.random()],
      [Math.random()*24, Math.random()],
      [Math.random()*24, Math.random()],
      [Math.random()*24, Math.random()],
      [Math.random()*24, Math.random()],
      [Math.random()*24, Math.random()],
      [Math.random()*24, Math.random()],
    ]

    var y = _.map(data, _.last);
    var max =  Math.max.apply(null, y);
    max = Math.ceil(max*10)/10;

    var angle = d3.scale.linear()
        .domain([0, 24])
        .range([0, 2 * Math.PI]);

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

    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(max*10).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(20)")
        .style("text-anchor", "middle")
        .text(function(d) { return d; });

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

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

    var color = d3.scale.category20();

    var line = d3.svg.line.radial()
          .angle(function(d) {
            return angle(d[0]);
          })
          .radius(function(d) {
            return r(d[1]);
          });
      

    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);
          });

  </script>

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM