D3具有可变X和Y的条形图(条形的宽度和高度可变)

时间:2019-02-11 08:33:34

标签: d3.js bar-chart

我正在尝试绘制一个条形图,该条形图将基于json数据的条形具有可变的宽度(基于json中的Weight字段)和高度(基于json中的频率字段)。

目前,我得到了一些结果,但是条之间存在一些差距。似乎我对X或Width的计算错误。

有人可以指出我正确的方向吗?

https://imgur.com/a/KyG2Aql

数据如下所示。

var data = [{
        "letter": "A",
        "Weight": 10,
        "frequency": 60,
        "xPos": 2.5
    },
    {
        "letter": "B",
        "Weight": 10,
        "frequency": 25,
        "xPos": 15
    },
    {
        "letter": "C",
        "Weight": 20,
        "frequency": 55,
        "xPos": 40
    }
];

我下面有一个codepen。

https://codepen.io/poorJSDev/pen/vbReOm

1 个答案:

答案 0 :(得分:1)

由于您既需要了解当前条目的权重(针对宽度),又要了解所有先前条目的权重之和(针对偏移),所以饼图布局似乎非常适合该任务(因为它提供切片的起始角度和终止角度)。您要做的就是将角度映射到宽度。

<!DOCTYPE html>
<head>
  <meta charset="utf-8">
  <script src="https://d3js.org/d3.v4.min.js"></script>
  <style>
    body { margin:0;position:fixed;top:0;right:0;bottom:0;left:0; }
  </style>
</head>

<body>
  <script>
    // Feel free to change or delete any of the code you see in this editor!
    var svg = d3.select("body").append("svg")
      .attr("width", 500)
      .attr("height", 200)

    var data = [{
      freq: 60,
      weight: 10
    }, {
      freq: 25,
      weight: 10
    }, {
      freq: 55,
      weight: 20
    }];
    
    var xScale = d3.scaleLinear()
    	.domain([0, Math.PI * 2])
    	.range([0, 500]);
    
    var yScale = d3.scaleLinear()
    	.domain([0, 80])
    	.range([200, 0]);
    
    var pie = d3.pie()
    	.sortValues(null)
    	.value(function(d){ return d.weight; });
    var adjustedData = pie(data);
    
    var rects = svg.selectAll('rect')
    	.data(adjustedData);
    
    rects.enter()
    	.append('rect')
    	.style('fill', 'blue')
    	.style('stroke', 'black')
    .merge(rects)
    	.attr('x', function(d) { return xScale(d.startAngle); })
    	.attr('width', function(d) { return xScale(d.endAngle) - xScale(d.startAngle); })
    	.attr('y', function(d) { return yScale(d.data.freq); })
    	.attr('height', function(d) { return yScale(0) - yScale(d.data.freq); });
    
  </script>
</body>