【问题标题】:D3 v4 - make a horizontal bar chart with fixed widthD3 v4 - 制作固定宽度的水平条形图
【发布时间】:2018-02-23 15:09:25
【问题描述】:

我使用 d3 v4 制作了一个水平条形图,除了一件事外,它工作正常。我无法固定条形高度。我目前正在使用带宽(),如果我用固定值替换它(15),问题是它与 y 轴标签/刻度线不对齐http://jsbin.com/gigesi/3/edit?html,css,js,output

var w = 200;
var h = 400;
var svg = d3.select("body").append("svg")
            .attr("width", w)
            .attr("height", h)
            .attr("transform", "translate(80,30)");

var data = [
            {Item: "Item 1", count: "11"},
            {Item: "Item 2", count: "14"},
            {Item: "Item 3", count: "10"},
            {Item: "Item 4", count: "14"}
           ];

var xScale = d3.scaleLinear()
               .rangeRound([0,w])
               .domain([0, d3.max(data, function(d) {
                   return d.count;
               })]);

var yScale = d3.scaleBand()
               .rangeRound([h,0]).padding(0.2)
               .domain(data.map(function(d) {
                   return d.Item;
             }));

var yAxis = d3.axisLeft(yScale);
svg.append('g')
   .attr('class','axis')
   .call(yAxis);
svg.selectAll('rect')
   .data(data)
   .enter()
   .append('rect')
       .attr('width', function(d,i) {
           return xScale(d.count);
        })
       .attr('height', yScale.bandwidth())
       .attr('y', function(d, i) {
           return yScale(d.Item);
       }).attr("fill","#000");

【问题讨论】:

  • 我尝试进行此更改 .attr('height', 15 + this.data.length / this.yScale.bandwidth()) 但这无助于与数据长度时的刻度对齐有 1 或 2 个条目。

标签: d3.js height bar-chart fixed


【解决方案1】:

您提供的链接中的 y 轴 似乎偏离了 SVG。 (也许你有 SVG 的 overflow: visible;

无论如何,我在图表中添加了一些边距,以便整个图表可见。这是(忽略链接描述):

DEMO: H BAR CHART WITH HEIGHT POSITIONING TO THE TICKS

相关代码改动:

  1. 当您使用比例尺时,高度是在其中计算的。你只需要使用.bandWidth()

    .attr('height', yScale.bandwidth())
    
  2. 添加边距并转换轴和条形以使整个图表可见: :我正在分配边距,以便y-axis 位于 SVG 的视口内,这也使得根据刻度值调整左边距更容易。我认为这应该是一种标准做法。 此外,如果您注意到,rectsbars 现在是 <g class="bars"></g> 的一部分。如果您愿意,请检查 DOM。这对于包含大量元素的复杂图表很有用,但它始终是一个好习惯。

    var margin = {top: 10, left: 40, right: 30, bottom: 10};
    
    var xScale = d3.scaleLinear()
          .rangeRound([0,w-margin.left-margin.right])
    
    var yScale = d3.scaleBand()
         .rangeRound([h-margin.top-margin.bottom,0]).padding(0.2)
    
    svg.append('g')
       .attr('class','axis')
       .attr('transform', 'translate(' + margin.left+', '+margin.top+')')
    

尝试更改数据,条形高度将根据刻度进行调整和对齐。希望这可以帮助。如果您有任何问题,请告诉我。

编辑: 最初,我认为您在将条形图放置在 y 刻度的中心时遇到了问题,但正如您所说,您需要固定高度条形图,这里是对上述代码的快速添加,可以让您做到这一点。我将很快添加另一种使用填充(内部和外部)的方法。

Updated JS BIN

为了将条形图准确定位在轴刻度的位置,我将条形图从顶部移动到由.bandWidth() 计算的刻度带宽,它的位置将从右开始刻度线,现在从中减去 所需高度的一半,以便条形的中心与刻度线 y 匹配。希望这能解释。

.attr('height', 15)
.attr('transform', 'translate(0, '+(yScale.bandwidth()/2-7.5)+')')

【讨论】:

  • 嗨,Shashank,感谢您的回复。如果您注意到我已经在使用带宽()。我想要的是固定带高,而与数据集无关。所以说它应该总是 15。手动设置高度的问题是条形图与刻度和 y 轴不对齐。我认为线索在 paddingInner / outer 中,但这就是我感到困惑的地方。
  • 对不起,问题中的错字应该是固定高度而不是固定宽度。
  • 用新链接更新了答案。检查一下。
  • 非常感谢!!它就像一个魅力.. 所以 7.5 我知道你正在使用所需带宽的一半.. 但是为什么 yScale.bandwidth() 的前一半?你能解释一下公式背后的原因吗?仅仅因为我认为这在制作双条形图时也会有所帮助?
  • 哦,不用担心。我更仔细地查看了您的解决方案..您正在将栏转换到正确的位置..那更简单!再次感谢
猜你喜欢
  • 2013-07-06
  • 1970-01-01
  • 2020-03-30
  • 2021-10-04
  • 1970-01-01
  • 1970-01-01
  • 2015-02-08
  • 2017-02-19
  • 1970-01-01
相关资源
最近更新 更多