我有一个堆叠here。我正在尝试使用D3更新模式创建一个简单的示例。单击更新按钮从数据中随机选择并更新图形。这种情况正在发生,但是它会将新图形放在当前图形之上,而不是删除当前图形。
我正在使用exit()
remove()
,但显然使用不正确。
答案 0 :(得分:2)
我认为您的最大问题是,您要在每次更新时创建新的比例尺和轴,而您应该只是通过它们各自的域向比例尺提供更新的数据,然后在每个轴上再次调用它们。
此外,当您在.enter
(x,y,宽度和高度属性)上放置新条形图时,您对应该.update
的旧条形图没有做任何操作。因此,您还必须放置那些先前存在的条形图(否则条形图看起来会相互重叠)。
<!DOCTYPE html>
<html>
<head>
<script data-require="d3@4.0.0" data-semver="4.0.0" src="https://d3js.org/d3.v4.min.js"></script>
</head>
<body>
<div class="chart-container"></div>
<button id="btn">Update</button>
<script>
var originalData = [{
"date": "Jan",
"value": 1507
},
{
"date": "Feb",
"value": 1600
},
{
"date": "Mar",
"value": 1281
},
{
"date": "Apr",
"value": 1898
},
{
"date": "May",
"value": 1749
},
{
"date": "June",
"value": 1270
},
{
"date": "July",
"value": 1712
},
{
"date": "Aug",
"value": 1270
},
{
"date": "Sept",
"value": 1257
},
{
"date": "Oct",
"value": 1257
},
{
"date": "Nov",
"value": 1277
},
{
"date": "Dec",
"value": 1057
}
];
///////////////////////////// Update function
function randomizeData(data) {
var rand = Math.floor(Math.random() * data.length) + 2
var newData = data.slice(0, rand);
update(newData)
console.log(newData)
}
///////////////////////////// Create SVG
var w = 400;
var h = 250;
var margin = {
top: 20,
bottom: 40,
left: 40,
right: 20
}
var width = w - margin.left - margin.right
var height = h - margin.top - margin.bottom
var svg = d3.select(".chart-container").append("svg")
.attr("id", "svg")
.attr("width", w)
.attr("height", h)
var chart = svg.append('g')
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var x = d3.scaleBand()
.range([0, width])
.padding(0.1)
var y = d3.scaleLinear()
.rangeRound([height, 0])
var xAxis = chart.append('g')
var yAxis = chart.append('g')
///////////////////////////////// Update function
function update(graphData) {
// Recalc domains based on new data
x.domain(graphData.map(function(d) {
return d.date
}));
y.domain([0, d3.max(graphData, function(d) {
return d.value;
})]);
// Redraw axes based on new data
xAxis.call(d3.axisBottom(x)).attr("transform", "translate(0," + height + ")")
yAxis.call(d3.axisLeft(y))
var u = chart.selectAll(".bar")
.data(graphData);
// Enter
u.enter()
.append("rect")
.classed('bar', true)
.attr('x', function(d) {
return x(d.date)
})
.attr("width", x.bandwidth())
.attr("y", function(d, i) {
return y(d.value);
})
.attr("height", function(d, i) {
return height - y(d.value);
});
// Update
u.attr('x', function(d) {
return x(d.date)
})
.attr("width", x.bandwidth())
.attr("y", function(d, i) {
return y(d.value);
})
.attr("height", function(d, i) {
return height - y(d.value);
});
// Exit
u.exit()
.remove();
}
randomizeData(originalData);
var button = document.getElementById('btn');
button.addEventListener('click', () => randomizeData(originalData));
</script>
</body>
</html>
答案 1 :(得分:1)
只需从更新功能中删除X,Y比例尺和轴,并在更新内使用remove()
exit()
。
///////////////////////////// Update function
function doUpdate(gdata){
var rand = Math.floor(Math.random()*data.length)+2
var newData = data.slice(0, rand);
update(newData)
}
///////////////////////////// Create SVG
var w = 400;
var h = 250;
var margin = {
top: 20,
bottom: 40,
left: 40,
right: 20
}
var width = w - margin.left - margin.right
var height = h - margin.top - margin.bottom
var svg = d3.select(".chart-container").append("svg")
.attr("id", "svg")
.attr("width", w)
.attr("height", h)
var chart = svg.append('g')
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var x = d3.scaleBand()
.range([0, width])
.padding(0.1)
.domain(data.map(function(d) {
return d.date
}));
var y = d3.scaleLinear()
.rangeRound([height, 0])
.domain([0, d3.max(data, function(d) {
return d.value;
})]);
var xAxis = chart.append('g')
.classed('x-axis', true)
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x))
var yAxis = chart.append('g')
.classed('y-axis', true)
.call(d3.axisLeft(y))
///////////////////////////////// Update function
function update(graphData){
console.log(graphData,graphData.length)
var u = chart.selectAll(".bar")
.remove()
.exit()
.data(graphData);
u.enter()
.append("rect")
.classed('bar', true)
.attr('x', function(d){
return x(d.date)
})
.attr("width", x.bandwidth())
.attr("y", function (d, i) {
return y(d.value);
})
.attr("height", function(d,i){
return height - y(d.value);
});
}
var button = document.getElementById('btn');
button.addEventListener('click', doUpdate);
doUpdate(data);