首页 > 解决方案 > D3.js 将饼图转换为频谱显示的方法

问题描述

我正在尝试为光谱显示创建一个 d3 模板,主要针对定性数据。想象一下这样的事情:

在此处输入图像描述

我有一个半圆:

var margins = {top:250, bottom:300, left:250, right:100};

var height = 600;
var width = 900;

var totalWidth = width+margins.left+margins.right;
var totalHeight = height+margins.top+margins.bottom;

var svg = d3.select('body')
    .append('svg')
    .attr('width', totalWidth)
    .attr('height', totalHeight);

var graphGroup = svg.append('g')
    .attr('transform', "translate("+margins.left+","+margins.top+")");

var pie = d3.pie()
            .value(function(d){return d})
            .sort(null);

var outerRadius = (400 / 2);
var innerRadius = 100;

var arc = d3.arc()
  .innerRadius(innerRadius)
  .outerRadius(outerRadius)
  .startAngle(0)
  .endAngle(Math.PI);

var arcLine = d3.arc()
  .innerRadius(innerRadius)
  .outerRadius(outerRadius);

/*
var pieG = graphGroup.selectAll(".arc")
    .data(pie(data))
  .enter().append("g")
    .attr("class", "arc");
*/

var path = graphGroup.append('path')
  .attr("d", arc)
  .attr("transform", 'rotate(-90)')
  .style('stroke','#000')
  .style('stroke-width',"2px")
  .style('fill', "none");
  
/*
var semicircle = pieG.append("path")
   .attr("fill","white")
   .attr("d", d3.arc()
     .endAngle(Math.PI)
     .startAngle(percentage * Math.PI)
     .outerRadius(radius - 10)
     .innerRadius(radius - 70));
*/
   <script src="https://d3js.org/d3.v5.min.js"></script>

然后我恍然大悟;如果这个模板是可重复使用的,我将不得不从头开始计算“段”。假设我有 6 个类似上图的类别,那么我必须每 30 度迭代一次。而且我完全不确定这将如何工作-以下是微弱的尝试:

var segmentLines = graphGroup.append('line')
    .attr('x1',???)
    .attr('x2',???)
    .attr('y1',???)
    .attr('y2',???);

即使我找到了正确的 xs 和 ys,那也只是 1 行——我总共需要 5 行来显示 6 个类别的频谱。天堂禁止我有 20 个类别——我无法找到使其规模化的方法。

问题

d3 是否有任何专门的方法可以用于频谱显示?如果不是,我的饼图方法是不是最好的方法?它会是可扩展的吗?为了便于说明,假设我们有一个变量,例如:

var categories = 6;

这样,根据这个数字,饼图/甜甜圈图将被切割成那么多块。(因此是模板式图)。

标签: javascriptd3.js

解决方案


您所需要的只是一个饼图生成器...

var pie = d3.pie()
    .startAngle(-Math.PI/2)
    .endAngle(Math.PI/2);

...您根据以下数据向其传递数据数组categories

var data = d3.range(categories).map(()=>1);

这是一个演示:

var height = 300;
var width = 500;

var categories = 6;
var data = d3.range(categories).map(()=>1);

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

var graphGroup = svg.append('g')
  .attr('transform', "translate(250,250)");

var pie = d3.pie()
	.startAngle(-Math.PI/2)
  .endAngle(Math.PI/2);

var outerRadius = (150);
var innerRadius = 100;

var arc = d3.arc()
  .innerRadius(innerRadius)
  .outerRadius(outerRadius);

var path = graphGroup.selectAll(null)
  .data(pie(data))
  .enter()
.append('path')
  .attr("d", arc)
  .style('stroke', '#000')
  .style('stroke-width', "2px")
  .style('fill', "none");
  
  var path2 = graphGroup.selectAll(null)
  .data(pie(data))
  .enter()
.append('path')
  .attr("d", function(d){
    return arc.innerRadius(150)
      .outerRadius(200)(d)
  })
  .style('stroke', '#000')
  .style('stroke-width', "2px")
  .style('fill', "none");
<script src="https://d3js.org/d3.v5.min.js"></script>


推荐阅读