D3.js 条形图中列的最大宽度

D3.js 条形图中列的最大宽度,d3.js,D3.js,我正在寻找一种在图表中限制列宽的方法,我相信这应该是相对容易的,但我找不到一种方法 我正在从一些动态数据填充一个图表,其中列的数量可能会有很大的变化——在1到20之间 e、 g:csv样本 Location,Col1 "Your house",20 Location,Col1,Col2,Col3,Col4,Col5 "My House",12,5,23,1,5 这很好,列的宽度是动态的,但是当数据中只有一列时,我的结果是一条756宽的条(整个图表),我不喜欢这种方式 我想做的是,不管数据的列

我正在寻找一种在图表中限制列宽的方法,我相信这应该是相对容易的,但我找不到一种方法

我正在从一些动态数据填充一个图表,其中列的数量可能会有很大的变化——在1到20之间

e、 g:csv样本

Location,Col1
"Your house",20

Location,Col1,Col2,Col3,Col4,Col5
"My House",12,5,23,1,5
这很好,列的宽度是动态的,但是当数据中只有一列时,我的结果是一条756宽的条(整个图表),我不喜欢这种方式

我想做的是,不管数据的列数是多少,最大列宽只有100px

下面是我的图表脚本

非常感谢,

<script>
var margin = {
    top : 40,
    right : 80,
    bottom : 80,
    left : 40
}, 
width = 960 - margin.left - margin.right, 
height = 500 - margin.top - margin.bottom;

var x = d3.scale.linear().range([ 0, width ]);

var y = d3.scale.linear().range([ height, 0 ]);

var x0 = d3.scale.ordinal()
    .rangeRoundBands([0, width], .05);

var x1 = d3.scale.ordinal();

var y = d3.scale.linear()
    .range([height, 0]);

var chart = d3.select("body").append("svg")
    .attr("class","chart")
    .attr("width", width + margin.left + margin.right)
    .attr("height", height + margin.top + margin.bottom)
    .append("g")
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

var legendChart = d3.select("body").append("svg")
    .attr("class","chart")
    .attr("width", width + margin.left + margin.right)
    .attr("height", height + margin.top + margin.bottom)
    .append("g")
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")");


d3.csv("/sampledata.csv.txt", function(error, data) {
    // Use the first row of csv for header names 
    var reasonNames = d3.keys(data[0]).filter(function(key) {
        return key !== "Location";
    });
    //console.log(reasonNames);

    data.forEach(function(d) {
        d.reasons = reasonNames.map(function(name) {
            return {
                name : name,
                value : +d[name]
            };
        });
        //console.log(d.reasons);
    });

    x0.domain(data.map(function(d) {return d.Location; }));
    x1.domain(reasonNames).rangeRoundBands([0, x0.rangeBand()]);

    console.log(x0.rangeBand());

    y.domain([0, d3.max(data, function(d) { return d3.max(d.reasons, function(d) { return d.value; }); })]);

    var maxVal = d3.max(data, function(d) { return d3.max(d.reasons, function(d) { return d.value; }); });
    //console.log(maxVal);

    var xAxis = d3.svg.axis()
        .scale(x0)
        .orient("bottom");

    var yAxis = d3.svg.axis()
        .scale(y)
        .orient("left")
        //.tickFormat(d3.format(".2s"));

    chart.append("g")
        .attr("class", "x axis")
        .attr("transform", "translate(0," + height + ")")
        .call(xAxis);

    chart.append("g")
        .attr("class", "y axis")
        .call(yAxis);

    var location = chart.selectAll(".name")
        .data(data)
      .enter().append("g")
        .attr("class", "g")
        .attr("transform", function(d) { return "translate(" + x0(d.Location) + ",0)"; });

    location.selectAll("rect")
        .data(function(d) { return d.reasons; })
      .enter().append("rect")
        .attr("width", x1.rangeBand()-2)
        .attr("x", function(d) { return x1(d.name); })
        .attr("y", function(d) { return y(d.value); })
        .attr("height", function(d) { return height - y(d.value); })
        .style("fill", function(d,i) { return "#"+3+"9"+i; /*color(d.name);*/ });

    chart.selectAll("text")
        .data(data)
      .enter().append("text")
        .attr("x", function(d) { return x1(d.name)+ x.rangeBand() / 2; })
        .attr("y", function(d) { return y(d.value); })
        .attr("dx", -3) // padding-right
        .attr("dy", ".35em") // vertical-align: middle
        .attr("text-anchor", "end") // text-align: right
        .text("String");

    var legend = legendChart.selectAll(".legend")
        .data(reasonNames.slice().reverse())
        .enter()
        .append("g")
        .attr("class", "legend")
        .attr("transform", function(d, i) { return "translate(0," + i * 20 + ")";
    });

    legend.append("rect")
        //.attr("x", width - 18)
        .attr("x", 18)
        .attr("width", 18)
        .attr("height", 18)
        .style("fill", function(d, i) {/*console.log(i);*/return "#" + 3 + "9" + i;
    });

    legend.append("text")
        //.attr("x", width - 24)
        .attr("x", 48)
        .attr("y", 9).attr("dy",".35em")
        //.style("text-anchor", "end")
        //.text(function(d,i) { return String.fromCharCode((65+i))+i; });
        .text(function(d) { return d; });
    });


</script>

var保证金={
前40名,
右:80,,
底部:80,
左:40
}, 
宽度=960-margin.left-margin.right,
高度=500-margin.top-margin.bottom;
var x=d3.scale.linear()范围([0,宽度]);
变量y=d3.scale.linear().range([height,0]);
var x0=d3.scale.ordinal()
.rangeRoundBands([0,宽度],.05);
var x1=d3.scale.ordinal();
变量y=d3.scale.linear()
.范围([高度,0]);
var chart=d3.选择(“主体”).追加(“svg”)
.attr(“类别”、“图表”)
.attr(“宽度”,宽度+边距。左侧+边距。右侧)
.attr(“高度”,高度+边距。顶部+边距。底部)
.附加(“g”)
.attr(“转换”、“平移”(+margin.left+)、“+margin.top+”);
var legendChart=d3.选择(“正文”).追加(“svg”)
.attr(“类别”、“图表”)
.attr(“宽度”,宽度+边距。左侧+边距。右侧)
.attr(“高度”,高度+边距。顶部+边距。底部)
.附加(“g”)
.attr(“转换”、“平移”(+margin.left+)、“+margin.top+”);
d3.csv(“/sampledata.csv.txt”),函数(错误,数据){
//使用csv的第一行作为标题名称
var reasonNames=d3.keys(数据[0]).filter(函数(键){
返回键!=“位置”;
});
//console.log(reasonNames);
data.forEach(函数(d){
d、 原因=reasonNames.map(函数(名称){
返回{
姓名:姓名,,
值:+d[名称]
};
});
//console.log(d.reasons);
});
域(data.map(函数(d){返回d.Location;}));
x1.domain(reasonNames).rangeRoundBands([0,x0.rangeBand()]);
console.log(x0.rangeBand());
y、 域([0,d3.max(数据,函数(d){返回d3.max(d.reasons,函数(d){返回d.value;};})]);
var maxVal=d3.max(数据,函数(d){返回d3.max(d.reasons,函数(d){返回d.value;});});
//console.log(maxVal);
var xAxis=d3.svg.axis()
.比例(x0)
.东方(“底部”);
var yAxis=d3.svg.axis()
.比例(y)
.东方(“左”)
//.tick格式(d3格式(“.2s”);
图表.附加(“g”)
.attr(“类”、“x轴”)
.attr(“变换”、“平移(0)”、“高度+”)
.呼叫(xAxis);
图表.附加(“g”)
.attr(“类”、“y轴”)
.呼叫(yAxis);
变量位置=图表。选择全部(“.name”)
.数据(数据)
.enter().append(“g”)
.attr(“类别”、“g”)
.attr(“transform”,函数(d){return”translate(“+x0(d.Location)+”,0)”;});
位置。选择全部(“rect”)
.data(函数(d){返回d.reasons;})
.enter().append(“rect”)
.attr(“宽度”,x1.rangeBand()-2)
.attr(“x”,函数(d){返回x1(d.name);})
.attr(“y”,函数(d){返回y(d.value);})
.attr(“高度”,函数(d){返回高度-y(d.value);})
.style(“fill”,函数(d,i){return“#”+3+“9”+i;/*color(d.name);*/});
图表。选择全部(“文本”)
.数据(数据)
.enter().append(“文本”)
.attr(“x”,函数(d){返回x1(d.name)+x.rangeBand()/2;})
.attr(“y”,函数(d){返回y(d.value);})
.attr(“dx”,-3)//右填充
.attr(“dy”,“.35em”)//垂直对齐:中间对齐
.attr(“文本定位”,“结束”)//文本对齐:右
.文本(“字符串”);
变量图例=图例。选择全部(“.图例”)
.data(reasonNames.slice().reverse())
.输入()
.附加(“g”)
.attr(“类”、“图例”)
.attr(“转换”,函数(d,i){返回“转换(0,+i*20+”)”;
});
图例。追加(“rect”)
//.attr(“x”,宽度-18)
.attr(“x”,18)
.attr(“宽度”,18)
.attr(“高度”,18)
.style(“fill”,函数(d,i){/*console.log(i);*/return“#”+3+“9”+i;
});
图例。追加(“文本”)
//.attr(“x”,宽度-24)
.attr(“x”,48)
.attr(“y”,9).attr(“dy”,“.35em”)
//.style(“文本锚定”、“结束”)
//.text(函数(d,i){返回字符串.fromCharCode((65+i))+i;});
.text(函数(d){return d;});
});

实现这一点的最简单方法是更改行

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


您可能还需要调整起始位置和/或填充。

我可以使用上述答案更改条的宽度。但不幸的是,当图表中只有一个条形并且它使用了最大宽度集时,我的X轴标签没有对齐

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]));

设置列的绝对最大宽度不允许对不同的屏幕分辨率、div大小等进行正确渲染

在我的例子中,我只是希望在列数本身很小的情况下,列不要看起来太大 我发现,通过改变最大宽度(所有列都适合的位置)、内部和外部填充,可以更轻松、更直接地使用比例定义

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)
渲染绘图时,我只运行了一个switch/if-else语句,它指定了不同的填充值。要打印的列数越少,我使用的外部填充(最终是内部填充)值就越大


这样,我就保留了绘图。

如果有人卡在起始位置上,调整起始位置的代码:

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

注:参考拉尔斯的答案。

为了完整起见,完整答案如下:

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) )
// 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])
}`
(coffeescript语法)

注t
// 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])
}`