数据更新时,我无法从条形图中删除条形。我希望 .exit((.remove(( 可以工作。但是当我更新时,两个条形图仍然存在。
最低版本在gh-pages上运行,您需要使用下拉菜单来开始使用它。目前,第一个数据文件 data1.json 未加载。
加载文件时,仅显示与先前渲染中的名称关联的条形。再次单击下拉菜单中的同一文件时,将显示其他栏。因此,必须单击两次文件才能正确显示。
如果初始呈现仅显示共同的条形,那么这就解释了为什么页面首次加载时它是空白的,没有任何共同点。
无论如何,显然这不是我想要的行为。
代码在github和jsFiddle上
var newRects0 = g0.selectAll(".bar")
.data(data, function(d) {
return d.name;
});
// newRects0.selectAll(".bar").remove();
newRects0.enter()
.append('rect')
.attr('x', function(d, i) {
return x(d.name);
})
// .attr('opacity', 0.33)
.attr('width', x.bandwidth())
.attr('y', height)
.attr('height', 0)
.attr("transform", "translate(0,0)")
.style('fill', 'gray')
.attr("class", function(d, i) {
return "group" + i + " bar"
});
newRects0.exit().remove();
newRects0.transition()
.duration(100)
.delay(function(d, i) {
return i * 15
})
.attr("x", function(d) {
return x(d.name);
})
.attr("y", function(d, i) {
return y(d.clocktime);
})
.attr("height", function(d, i) {
return height - y(d.clocktime)
})
.attr("width", x.bandwidth());
x 轴和 y 轴正在正确更改。
更新:
我现在正在尝试使用 Bostock 的更新模式 III 条形出现,然后在我认为 750 毫秒后消失。
我已经大大简化了代码,它现在在github,gh-pages和jsFiddle上。
<!DOCTYPE html>
<meta charset="utf-8">
<style>
.container {
margin-left: 0px;
}
</style>
<script src="https://cdnjs.cloudflare.com/ajax/libs/tether/1.4.0/js/tether.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" crossorigin="anonymous">
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/js/bootstrap.min.js" crossorigin="anonymous"></script>
<body>
<ul class="nav nav-tabs">
<li class="nav-item">
<a class="nav-link active" href="#">Home</a>
</li>
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" data-toggle="dropdown" href="#" role="button" aria-haspopup="true" aria-expanded="false">Data</a>
<div class="dropdown-menu">
<a class="dropdown-item" id="defaultInput" value="one" href="#">data1.json</a>
<a class="dropdown-item" id="updateInput" value="two" href="#">data2.json</a>
</div>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Link</a>
</li>
<li class="nav-item">
<a class="nav-link disabled" href="#">Disabled</a>
</li>
</ul>
<div class="container-fluid">
<div class="row">
<div class="col-md-12">
<div id="race_graph">
</div>
</div>
</div>
</div>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
// set the dimensions and margins of the graph
var margin = {
top: 70,
right: 50,
bottom: 100,
left: 80
},
width = 1400 - margin.left - margin.right,
height = 600 - margin.top - margin.bottom;
var parseTime = d3.timeParse("%M:%S");
var timeformat = d3.timeFormat("%M:%S");
// set the domains and ranges
var x = d3.scaleBand()
.range([0, width])
.padding([0.6]);
// temporal y-scale
var y = d3.scaleTime()
.range([height, 0]);
var xAxis = d3.axisBottom(x);
var yAxis = d3.axisLeft(y)
.ticks(7)
.tickFormat(d3.timeFormat("%M:%S"));
// Add main graph svg
var svg = d3.select("#race_graph")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom);
// Add groups for main bar chart
var g0 = svg.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
function defaultFunction() {
d3.json("data1.json", function(error, newdata) {
if (error) throw error;
data = newdata;
data.forEach(function(d) {
d.racetime = parseTime(d.racetime);
d.handicap = parseTime(d.handicap);
d.clocktime = parseTime(d.clocktime);
d.place = +d.place;
d.points = +d.points;
d.raceplace = +d.raceplace;
d.timeplace = +d.timeplace;
})
update();
});
}
function updateFunction() {
d3.json("data2.json", function(error, newdata) {
if (error) throw error;
data = newdata;
data.forEach(function(d) {
d.racetime = parseTime(d.racetime);
d.handicap = parseTime(d.handicap);
d.clocktime = parseTime(d.clocktime);
d.place = +d.place;
d.points = +d.points;
d.raceplace = +d.raceplace;
d.timeplace = +d.timeplace;
})
update(data);
});
}
function update(err, newdata) {
// set the domains
x.domain(data.map(function(d) {
return d.name
}));
// set domain temporal y-scale
y.domain([parseTime('00:00'), d3.max(data, function(d) {
return d.clocktime
})]);
// Add the X Axis
svg.select(".x.axis").call(xAxis);
svg.select(".x.axis").remove();
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(" + (margin.left) + "," + (height + margin.top) + ")")
.call(xAxis)
.selectAll("text")
.attr("transform", "translate(-100,0)")
.style("text-anchor", "end")
.style("font", "7px times")
.attr("class", function(d, i) {
return "groupText" + i + " xAxisText"
})
.attr("dx", "-.8em")
.attr("dy", ".15em")
.attr("transform", "rotate(-75)");
// Add the y axis on left
svg.select(".y.axis").remove();
svg.append("g")
.attr("class", "y axis")
.attr("transform", "translate(" + (margin.left) + "," + margin.top + ")")
.call(yAxis);
var t = d3.transition()
.duration(4000);
// JOIN new data with old elements
var newRects0 = g0.selectAll(".bar")
.data(data, function(d) {
return d;
});
// EXIT old elements not present in new data
newRects0.exit()
.transition(t)
.attr("x", function(d) {
return x(d.name);
})
.attr("y", function(d, i) {
return y(d.clocktime);
})
.attr("height", function(d, i) {
return height - y(d.clocktime)
})
// .attr("width", x.bandwidth())
.remove();
// UPDATE old elements present in new data
newRects0.attr("x", function(d) {
return x(d.name);
})
.attr("y", function(d, i) {
return y(d.clocktime);
})
.attr("height", function(d, i) {
return height - y(d.clocktime)
})
// .attr("width", x.bandwidth())
.style('fill', 'gray');
// ENTER new elements present in new data
newRects0.enter()
.append('rect')
.attr("x", function(d) {
return x(d.name);
})
.attr("y", function(d, i) {
return y(d.clocktime);
})
.attr("height", function(d, i) {
return height - y(d.clocktime)
})
.attr("width", x.bandwidth())
.style('fill', 'gray')
.attr("class", function(d, i) {
return "group" + i + " bar"
});
}; //closes update() function
document.getElementById("defaultInput")
.onclick = defaultFunction;
document.getElementById("updateInput")
.onclick = updateFunction;
defaultFunction();
</script>
</body>
谢谢
我终于找到了 Bostock 的示例更新模式 III,并将其应用于条形图。
这是github上的代码和gh-pages上的演示。
此模式中的阶段是,
- 将新数据与旧元素联接
- 退出新数据中不存在的旧元素
- 更新新数据中存在的旧元素
- 输入新数据中存在的新元素
我的绘制函数的第一行是:
d3.selectAll("svg").remove();
这将在创建新的 svg(取决于窗口大小(并使用要导入的新数据更新它之前清除 svg 和所有相关对象。
您可以单独选择要删除的矩形,但是如果轴根据新数据而更改,则可能值得删除所有内容并再次绘制轴。
编辑:我认为混淆在于"默认功能"/"更新功能"。
document.getElementById("defaultInput")
.onclick = defaultFunction;
document.getElementById("updateInput")
.onclick = updateFunction;
defaultFunction();
对于"updateInput",data1.json和data2.json分别由updateFunction和defaultFunction加载。
如果可以分离出图表功能,则有
function input1() {
d3.json("data1.json", function(error, data) {
if (error) {
return console.error(error);
} else
update(data);
})}
function input2() {
d3.json("data2.json", function(error, data) {
if (error) {
return console.error(error);
} else
update(data);
})}
function update (data){
remove old data;
parse new data;
make graph...
}
这应该可以澄清它。