我正在尝试在D3中创建一个范围条形图(参见a similar example) .
我找到了this answer,我能够将它自定义为我需要的东西,除了它使用古老版本的D3,数据是单独阵列的愚蠢格式,并且它没有响应(为什么这么多D3的东西出来了有没有回应?) .
我放弃了这种尝试,从头开始 . 我现在主要使用最新的D3和上面的SO问题中的一些想法,但数据显示不正确 . 当我调整大小时,条纹不可预测地增长和缩小,最终得到负宽度值,因为我更宽 .
我很感激帮助理解我对酒吧尺寸的错误 . 请注意,要观察不正确的行为,您必须展开代码段并调整窗口大小 .
let data = [
{ field: "Field Name 1", salary: [42, 65], bonusRange: [null, null] },
{ field: "Field Name 2", salary: [28, 58], bonusRange: [null, null] },
{ field: "Field Name 3", salary: [33, 57], bonusRange: [null, null] },
{ field: "Field Name 4", salary: [33, 50], bonusRange: [null, null] },
{ field: "Field Name 5", salary: [32, 44], bonusRange: [38, 52] },
{ field: "Field Name 6", salary: [27, 40], bonusRange: [null, null] }
];
const chartDiv = document.getElementById("chart");
const svg = d3.select(chartDiv).append("svg");
function redraw() {
svg.selectAll("g").remove();
const margin = 20;
const width = chartDiv.clientWidth - margin * 2;
const height = chartDiv.clientHeight - margin * 2;
svg
.attr("width", width)
.attr("height", height)
.attr("transform", `translate(${margin}, ${margin})`);
const xScale = d3
.scaleLinear()
.range([120, width - 10])
.domain([20, 70]);
const xAxis = d3.axisBottom(xScale);
const yScale = d3
.scaleLinear()
.range([0, height - margin])
.domain([-0.5, (data.length - 1) * 1.1]);
const yAxis = d3
.axisLeft(yScale)
.ticks(data.length)
.tickFormat(function(d, i) {
return data[i].field;
});
svg
.append("g")
.attr("class", "axis")
.call(xAxis)
.attr("transform", `translate(0, ${height - margin})`);
svg
.append("g")
.attr("class", "axis")
.call(yAxis)
.attr("transform", "translate(120, 0)");
svg
.append("g")
.attr("id", "bars")
.selectAll(".bar")
.data(data)
.enter()
.append("rect")
.style("fill", "#f61166")
.attr("class", "bar")
.attr("x", function(d) {
return xScale(d.salary[0]);
})
.attr("height", 25)
.attr("width", function(d) {
return xScale(d.salary[1] - d.salary[0]);
})
.attr("y", function(d, i) {
return yScale(i) - margin * 0.5;
});
}
redraw();
window.addEventListener("resize", redraw);
* {
box-sizing: border-box;
}
body {
padding: 10px;
}
#chart {
outline: 1px solid fuchsia;
height: 0;
overflow: hidden;
padding-top: 59.75%;
background: white;
position: relative;
}
#chart svg {
position: absolute;
top: 0;
left: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<div id="chart" class=""></div>
1 回答
你的代码需要大量的重构,你通常应该按照d3 update pattern来改变数据(或者在这种情况下是窗口的大小,ps . 我不是100%肯定这是一个好主意,因为我从来没有我的图表"responsive"就像这样,但似乎工作得很好)
换句话说,当你想要更新时不要使用
svg.selectAll("g").remove();
,你可以显然但这对d3来说并不是真正的惯用语 .我删除了重绘函数的所有追加并将它们放在包装函数中,因此我们可以通过类名或变量引用它们 .
我还将yScale变量放入了一个比例带,这样就可以更容易地根据数据调整图表的大小 .
我在下面添加了一个片段,希望很清楚这样的事情是如何完成的 .