Maximum width for column in bar chart

后端 未结 6 1058
天命终不由人
天命终不由人 2021-02-14 09:35

I\'m looking for a way of limiting the column width in a chart, I\'m sure this ought to be relatively easy but I cant find a way of doing it.

I\'m populating a chart fro

相关标签:
6条回答
  • 2021-02-14 09:40

    I am able to change the width of the bar using the above answer. But unfortunately, my X Axis labels are not aligned when there is a single bar in the chart and it uses the max width set.

    var tradeGroup = svg.selectAll("g.trade")
                .data(trades)
                .enter()
                .append("svg:g")
                .attr("class", "trade")
                .style("fill", function (d, i) {
                    return self.color(self.color.domain()[i]);
                })
                .style("stroke", function (d, i) {
                    return d3.rgb(self.color(self.color.domain()[i])).darker();
                });
    
    var aWidth = Math.min.apply(null, [x.rangeBand(), 100]);
    
    // Add a rect for each date.
    var rect = tradeGroup.selectAll("rect")
                .data(Object)
                .enter()
                .append("svg:rect")
                .attr("x", function (d) {                 
                    return x(d.x);
                })
                .attr("y", function (d) { return y( (d.y || 0) + (d.y0 || 0)); })
                .attr("height", function (d) { return y(d.y0 || 0) - y((d.y || 0) + (d.y0 || 0)); })
                .attr("width", Math.min.apply(null, [x.rangeBand(), 100]));
    
    0 讨论(0)
  • 2021-02-14 09:56

    Thought I'd share that I came up with a slightly different answer to this. I didn't want to hard code in a maximum bar width because 1) it wasn't responsive to different screen sizes and 2) it also required playing with the x-coordinate attribute or accepting some irregular spacing.

    Instead, I just set a minimum number of bars, based on the point where the bars became too wide (in my case, I found that less than 12 bars made my chart look weird). I then adjusted the scaleBand's range attribute, proportionately, if there were less than that number of bars. So, for example, if the minimum was set to 12 and there were only 5 items in the data, rather than rendering each of them at 1/5th of the full width, I scaled the range down to 5/12ths of the original width.

    Basically, something like this:

    // x is a scaleBand() that was previously defined, and this would run on update
    
    var minBarSlots = 12;
    
    if (data.length < minBarSlots) {
        x.range([0, width*(data.length/minBarSlots)])
    }
    else {
        x.range([0, width])
    }`
    
    0 讨论(0)
  • 2021-02-14 09:59

    Setting an absolute maximum width for the columns doesn't allow proper rendering for different screen resolutions, div sizes, etc.

    In my case, I just wanted the columns not to look so large when the number of columns itself is small I found it easier and more straight-forward to play with the scale definition, by changing the maximum width (where all columns will fit), their inner and outer paddings.

    var w = 600
    // var w = parseInt(d3.select(parentID).style('width'), 10) // retrieve the div width dynamically
    var inner_padding = 0.1
    var outer_padding = 0.8
    var xScale = d3.scale.ordinal().rangeRoundBands([0, w], inner_padding, outer_padding)
    

    When rendering the plot, I just ran a switch/if-else statement, which assigns different padding values. The lower the number of columns to plot, the greater the outer_padding (and eventually inner-padding) values I use.

    This way, I keep the plots responsive.

    0 讨论(0)
  • 2021-02-14 10:00

    For completeness the full answer would look like this:

    svg.selectAll(".bar")
      .data(data)
      .enter().append("rect")
      .attr("class", "bar")
      .attr("x", (d) -> x1(d.name) + (x1.rangeBand() - d3.min([x1.rangeBand(), 100]))/2)
      .attr("width", d3.min([x1.rangeBand(), 100]))
      .attr("y", (d) -> y(d.grade) )
      .attr("height", (d)-> height - y(d.value) )
    

    (coffeescript syntax)

    Note this include the full answer, the 'width' and the 'x' settings. Also 'x' settings is accounting for a when 100 width is not the min value.

    0 讨论(0)
  • 2021-02-14 10:01

    The easiest way to achieve this is by changing the line

    .attr("width", x1.rangeBand()-2)
    

    to

    .attr("width", Math.min(x1.rangeBand()-2, 100))
    

    You might also want to adjust the starting position and/or padding.

    0 讨论(0)
  • 2021-02-14 10:03

    Code for adjusting starting position if anyone is stuck on it:

    .attr("x", function(d, i) { return x1(d.seriesName) + (x1.rangeBand() - 100)/2 ;})
    

    P.S. : referring answer from Lars.

    0 讨论(0)
提交回复
热议问题