【问题标题】:D3 Bar Chart with Variable X and Y(variable width and height for bars)具有可变 X 和 Y 的 D3 条形图(条形的可变宽度和高度)
【发布时间】:2019-02-11 08:33:34
【问题描述】:

我正在尝试为基于 json 数据的条形图绘制一个具有可变宽度(基于 json 中的权重字段)和高度(基于 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
    }
];

我有一个下面相同的代码笔。

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

【问题讨论】:

  • 不清楚你想要实现什么——你有两个 xPos 作为一个字段,但似乎还想从权重比例计算 xPos ?
  • @CoderinoJavarino xPos 实际上不是数据的一部分。我计算了它,因为我不知道如何将权重与整体成比例。
  • 您翻译 bar-g 并给 bar-rect 一个 x,而您的 text 元素为空
  • 正x轴从什么时候开始在左边?

标签: d3.js bar-chart


【解决方案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>

【讨论】: