javascript - 如何限制 D3 条形图中的最大宽度
问题描述
我是 d3 条形图的新手,下面是我想在我的项目中使用的条形图的代码。
我只是想知道如何限制条形的最大宽度,因为当我只有一条记录时,条形的宽度变得非常大,实际上该条形占用了整个宽度,然后图形看起来不太好。d3 中是否有任何方法可以限制每个条的最大宽度。
<!DOCTYPE html>
<meta charset="utf-8">
<style> /* set the CSS */
body { font: 12px Arial;}
path {
stroke: steelblue;
stroke-width: 2;
fill: none;
}
.axis path,
.axis line {
fill: none;
stroke: grey;
stroke-width: 1;
shape-rendering: crispEdges;
}
.legend {
font-size: 16px;
font-weight: bold;
text-anchor: middle;
}
</style>
<body>
<div id="d3id" ></div>
<!-- load the d3.js library -->
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
var models = [
{
"model_name":"http://www.test.com",
"field1":19,
"field2":83
},
{
"model_name":"http://www.test2.com",
"field1":67,
"field2":93
},
{
"model_name":"http://www.test3.com",
"field1":10,
"field2":56
},
{
"model_name":"http://www.test4.com",
"field1":98,
"field2":43
},
{
"model_name":"http://www.test.com",
"field1":19,
"field2":83
},
{
"model_name":"f7",
"field1":67,
"field2":93
},
{
"model_name":"f8",
"field1":10,
"field2":56
},
{
"model_name":"f9",
"field1":98,
"field2":43
}
];
models = models.map(i => {
i.model_name = i.model_name;
return i;
});
var container = d3.select('#d3id'),
width = 500,
height = 300,
margin = {top: 30, right: 20, bottom: 30, left: 50},
barPadding = .3,
axisTicks = {qty: 5, outerSize: 0, dateFormat: '%m-%d'};
var svg = container
.append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", `translate(${margin.left},${margin.top})`);
var xScale0 = d3.scaleBand().range([0, width - margin.left - margin.right]).padding(barPadding);
var xScale1 = d3.scaleBand();
var yScale = d3.scaleLinear().range([height - margin.top - margin.bottom, 0]);
var xAxis = d3.axisBottom(xScale0).tickSizeOuter(axisTicks.outerSize);
var yAxis = d3.axisLeft(yScale).ticks(axisTicks.qty).tickSizeOuter(axisTicks.outerSize);
xScale0.domain(models.map(d => d.model_name));
xScale1.domain(['field1', 'field2']).range([0, xScale0.bandwidth()]);
yScale.domain([0, d3.max(models, d => d.field1 > d.field2 ? d.field1 : d.field2)]);
var model_name = svg.selectAll(".model_name")
.data(models)
.enter().append("g")
.attr("class", "model_name")
.attr("transform", d => `translate(${xScale0(d.model_name)},0)`);
/* Add field1 bars */
model_name.selectAll(".bar.field1")
.data(d => [d])
.enter()
.append("rect")
.attr("class", "bar field1")
.style("fill","#4267b2")
.attr("x", d => xScale1('field1'))
.attr("y", d => yScale(d.field1))
.attr("width", xScale1.bandwidth())
.attr("height", d => {
return height - margin.top - margin.bottom - yScale(d.field1)
});
/* Add field2 bars */
model_name.selectAll(".bar.field2")
.data(d => [d])
.enter()
.append("rect")
.attr("class", "bar field2")
.style("fill","#69b3a2")
.attr("x", d => xScale1('field2'))
.attr("y", d => yScale(d.field2))
.attr("width", xScale1.bandwidth())
.attr("height", d => {
return height - margin.top - margin.bottom - yScale(d.field2)
});
// Add the X Axis
svg.append("g")
.attr("class", "x axis")
.attr("transform", `translate(0,${height - margin.top - margin.bottom})`)
.call(xAxis);
// Add the Y Axis
svg.append("g")
.attr("class", "y axis")
.call(yAxis);
</script>
</body>
另外,如何调整标签以使其适合?请帮我。
解决方案
您可以通过在附加矩形时操作的宽度属性轻松实现这一点。
在这里,我正在检查矩形的宽度是否大于宽度/10 (500/10),然后保持恒定值 50,否则使用默认值。您可以使用任何逻辑来操纵它。
.attr("width", function(d) {
return xScale1.bandwidth() > width/10 ? width/10 : xScale1.bandwidth();
})
请在下面找到工作片段:
<!DOCTYPE html>
<meta charset="utf-8">
<style> /* set the CSS */
body { font: 12px Arial;}
path {
stroke: steelblue;
stroke-width: 2;
fill: none;
}
.axis path,
.axis line {
fill: none;
stroke: grey;
stroke-width: 1;
shape-rendering: crispEdges;
}
.legend {
font-size: 16px;
font-weight: bold;
text-anchor: middle;
}
</style>
<body>
<div id="d3id" ></div>
<!-- load the d3.js library -->
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
var models = [
{
"model_name":"http://www.test.com",
"field1":19,
"field2":83
},
/* {
"model_name":"http://www.test2.com",
"field1":67,
"field2":93
},
{
"model_name":"http://www.test3.com",
"field1":10,
"field2":56
},
{
"model_name":"http://www.test4.com",
"field1":98,
"field2":43
},
{
"model_name":"http://www.test.com",
"field1":19,
"field2":83
},
{
"model_name":"f7",
"field1":67,
"field2":93
},
{
"model_name":"f8",
"field1":10,
"field2":56
},
{
"model_name":"f9",
"field1":98,
"field2":43
} */
];
models = models.map(i => {
i.model_name = i.model_name;
return i;
});
var container = d3.select('#d3id'),
width = 500,
height = 300,
margin = {top: 30, right: 20, bottom: 30, left: 50},
barPadding = .3,
axisTicks = {qty: 5, outerSize: 0, dateFormat: '%m-%d'};
var svg = container
.append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", `translate(${margin.left},${margin.top})`);
var xScale0 = d3.scaleBand().range([0, width - margin.left - margin.right]).padding(barPadding);
var xScale1 = d3.scaleBand();
var yScale = d3.scaleLinear().range([height - margin.top - margin.bottom, 0]);
var xAxis = d3.axisBottom(xScale0).tickSizeOuter(axisTicks.outerSize);
var yAxis = d3.axisLeft(yScale).ticks(axisTicks.qty).tickSizeOuter(axisTicks.outerSize);
xScale0.domain(models.map(d => d.model_name));
xScale1.domain(['field1', 'field2']).range([0, xScale0.bandwidth()]);
yScale.domain([0, d3.max(models, d => d.field1 > d.field2 ? d.field1 : d.field2)]);
var model_name = svg.selectAll(".model_name")
.data(models)
.enter().append("g")
.attr("class", "model_name")
.attr("transform", d => `translate(${xScale0(d.model_name)},0)`);
/* Add field1 bars */
model_name.selectAll(".bar.field1")
.data(d => [d])
.enter()
.append("rect")
.attr("class", "bar field1")
.style("fill","#4267b2")
.attr("x", d => xScale1('field1'))
.attr("y", d => yScale(d.field1))
.attr("width", xScale1.bandwidth())
.attr("height", d => {
return height - margin.top - margin.bottom - yScale(d.field1)
});
/* Add field2 bars */
model_name.selectAll(".bar.field2")
.data(d => [d])
.enter()
.append("rect")
.attr("class", "bar field2")
.style("fill","#69b3a2")
.attr("x", d => xScale1('field2'))
.attr("y", d => yScale(d.field2))
.attr("width", function(d) {
return xScale1.bandwidth() > width/2 ? width/4 : xScale1.bandwidth();
})
.attr("height", d => {
return height - margin.top - margin.bottom - yScale(d.field2)
});
// Add the X Axis
svg.append("g")
.attr("class", "x axis")
.attr("transform", `translate(0,${height - margin.top - margin.bottom})`)
.call(xAxis);
// Add the Y Axis
svg.append("g")
.attr("class", "y axis")
.call(yAxis);
</script>
</body>
推荐阅读
- swift - Swift 4 如何将文本打印到标签
- python - 为什么 numpy 混合基本/高级索引取决于切片邻接?
- java - 在另一个线程中捕获库引发的异常(android)
- php - 如何在 Wordpress 中为自定义表格创建单个视图页面
- python - 通过 Django 网页执行循环 python 脚本
- qfiledialog - 无法使用 QFileDialog.getSaveFileName 保存为 csv
- python - pytorch 中的自适应池化如何工作?
- rust - 如何在不制作任何副本的情况下将 bytes::Bytes 转换为 &str?
- python - python字节数组print()给出错误的值
- c - 我自己的 malloc() 函数中的指针算术问题