Ваш код нуждается в значительном рефакторинге, в общем случае вы должны следовать шаблону обновления d3 всякий раз, когда вы хотите изменить данные (или размер окна в этом случае, ps. Я не уверен на 100%, что это хорошая идея, так как я никогда не делаю свои графики "отзывчивыми", как это, но, похоже, работает нормально )
Другими словами, не* Если вы хотите обновить *, используйте svg.selectAll("g").remove();
. Очевидно, вы можете, но это не совсем идиоматично для d3.
Я удалил все добавления из функции перерисовки и поместил их в функцию-обертку, чтобы мы могли ссылаться на нихлибо по имени класса, либо по переменной.
Я также превратил вашу переменную yScale в масштабную полосу, чтобы было проще изменить размер диаграммы на основе данных.
const yScale = d3.scaleBand()
.domain(data.map(d => d.field))
.padding(0.1)
.paddingOuter(0.1)
.paddingInner(0.1);
Я добавил фрагмент нижеНадеюсь, должно быть ясно, как это можно сделать.
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] }
];
chart(data);
function chart(data) {
var svg = d3.select("#chart"),
margin = {top: 55, bottom: 0, left: 85, right: 0},
width = parseInt(svg.style("width")) - margin.left - margin.right,
height = parseInt(svg.style("height")) - margin.top - margin.bottom;
const xScale = d3.scaleLinear()
.domain([20, 70]);
const yScale = d3.scaleBand()
.domain(data.map(d => d.field))
.padding(0.1)
.paddingOuter(0.1)
.paddingInner(0.1);
const xAxis = svg.append("g")
.attr("class", "x-axis")
const yAxis = svg.append("g")
.attr("class", "y-axis")
redraw(width, height);
function redraw(width, height) {
yScale.range([margin.top, height - margin.bottom])
svg.selectAll(".y-axis")
.attr("transform", `translate(${margin.left},0)`)
.call(d3.axisLeft(yScale)
.ticks(data.length)
.tickFormat(function(d, i) {
return data[i].field;
}));
xScale.range([margin.left, width - margin.right]);
svg.selectAll(".x-axis").transition().duration(0)
.attr("transform", `translate(0,${height})`)
.call(d3.axisBottom(xScale));
var bar = svg.selectAll(".bar")
.data(data)
bar.exit().remove();
bar.enter().append("rect")
.attr("class", "bar")
.style("fill", "#f61166")
.merge(bar)
.transition().duration(0)
.attr("width", function(d) {
return xScale(d.salary[1] - d.salary[0]) - xScale(0);
})
.attr("height", yScale.bandwidth())
.attr("y", d => yScale(d.field))
.attr("x", function(d) {
return xScale(d.salary[0]);
});
}
d3.select(window).on('resize', function() {
width = parseInt(svg.style("width")) - margin.left - margin.right,
height = parseInt(svg.style("height")) - margin.top - margin.bottom;
redraw(width, height);
});
}
body {
padding: 25px 25px 25px 25px;
font: 18px arial;
}
#chart {
outline: 1px solid fuchsia;
position: absolute;
width: 95%;
height: 95%;
}
<script src="https://d3js.org/d3.v5.min.js"></script>
<svg id="chart"></svg>