我有一个基本的条形图。 Bootstrap下拉菜单选择data1.json或data2.json中的数据。两者都只有键“A”,“B”,“C”和“D”。这意味着没有任何条形图正在退出或输入数据,它们都只是更新值。
我有用于为条形指定颜色的类,以便那些退出,更新和输入分别为红色,橙色和绿色。由于值仅更新,因此所有条形应仅为橙色。这是“A”的行为。但其他人变得“红色”,好像他们正在退出数据,而“绿色”就好像他们是新的输入数据一样。
为什么栏“B”,“C”和“D”的行为与栏“A”不同?对我而言“A”是正确的。
不幸的是,此代码段不起作用。我无法让它在jsFiddle中工作。
使用下拉菜单更改数据。
data1.json
[{
"name": "A",
"value": 5
},
{
"name": "B",
"value": 3
},
{
"name": "C",
"value": 2
},
{
"name": "D",
"value": 4
}
]
data2.json
[{
"name": "A",
"value": 3
},
{
"name": "B",
"value": 7
},
{
"name": "C",
"value": 4
},
{
"name": "D",
"value": 8
}
]
index.html
<!DOCTYPE html>
<meta charset="utf-8">
<style>
.container {
margin-left: 0px;
}
.exit {
fill: red;
}
.update {
fill: orange;
}
.enter {
fill: green;
}
#json {
max-height: 400px;
width: 200px;
overflow: scroll;
border: 2px solid gray;
border-radius: 15px;
}
</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="https://github.com/shanegibney/D3-v4-Bar-Chart-Update-Pattern">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" onclick="updateFunction('1')" href="# ">data1.json</a>
<a class="dropdown-item" onclick="updateFunction('2')" href="#">data2.json</a>
</div>
</li>
<li class="nav-item">
<a class="nav-link" href="https://github.com/shanegibney/D3-v4-Bar-Chart-Update-Pattern">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-8" id="race_graph">
</div>
<div id="json">
<!-- <pre class="col-md-4" id="json">hello</pre> -->
</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 = 1000 - margin.left - margin.right,
height = 600 - margin.top - margin.bottom;
var data1 = [{
"name": "A",
"value": 5
},
{
"name": "B",
"value": 3
},
{
"name": "C",
"value": 2
},
{
"name": "D",
"value": 4
}
]
var data2 = [{
"name": "A",
"value": 3
},
{
"name": "B",
"value": 7
},
{
"name": "C",
"value": 4
},
{
"name": "D",
"value": 8
}
]
// set the domains and ranges
var x = d3.scaleBand()
.range([0, width])
.padding([0.6]);
// temporal y-scale
var y = d3.scaleLinear()
.range([height, 0]);
var xAxis = d3.axisBottom(x);
var yAxis = d3.axisLeft(y)
.ticks(8);
// 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 + ")");
var index = 1;
updateFunction(index);
function updateFunction(index) {
// d3.json("data" + index + ".json", function(error, newdata) {
newdata = "data" + index;
// if (error) throw error;
data = newdata;
data.forEach(function(d) {
d.value = +d.value;
})
// To display json in html page
document.getElementById("json").innerHTML = "<pre>" + JSON.stringify(data, null, 4) + "</pre>";
update();
// });
}
function update(err, newdata) {
// set the domains
x.domain(data.map(function(d) {
return d.name
}));
// set domain temporal y-scale
y.domain([0, d3.max(data, function(d) {
return d.value;
})]).nice();
// 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);
// 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(750);
// 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()
.attr("class", function(d) {
return "exit bar";
}) // fill red
.transition(d3.transition()
// .delay(0)
.duration(750))
.attr("y", function(d) {
return height;
}) // old elements which are leaving the chart, their y position transitions to the xaxis
.attr("height", function(d) {
return 0;
}) // old elements which are leaving the chart, therir height trasnitions to 0
.remove();
// UPDATE old elements present in new data
newRects0.attr("class", function(d) {
return "update bar";
})
.transition(d3.transition()
.delay(1000))
.duration(750)
.attr("x", function(d) {
return x(d.name);
}) // old elememnts in new data transition to their new position
.attr("y", function(d) {
return y(d.value)
}) // old elememnts in new data transition to their y position
.attr("height", function(d, i) {
return height - y(d.value)
}); // old elememnts in new data transition to their correct height
// ENTER new elements present in new data
// EXIT and UPDATE above will not apply first time render as there is no change to the data.
newRects0.enter()
.append('rect')
.attr("class", "enter bar") // fill green
.attr("x", function(d) {
return x(d.name);
})
.attr("y", height) // bars start on xaxis or position y=height
.attr("height", function(d) {
return 0;
}) // bars start with zero height
.attr("width", x.bandwidth())
.transition(d3.transition()
.delay(2000))
.duration(750)
.attr("y", function(d, i) {
return y(d.value);
}) // after the transition bars goes to its correct y position
.attr("height", function(d, i) {
return height - y(d.value)
}); // after transition bar grows to its full height
}; // end of update() function
</script>
</body>
谢谢,
答案 0 :(得分:2)
您需要为data()
函数提供一个保持不变的密钥,因此它知道哪些新数据与旧数据相同。 d.name
应该比返回整个对象更好。这样的事情对我有用:
var newRects0 = g0.selectAll(".bar")
.data(data, function(d) {
return d.name;
});
这是一个工作小提琴:https://jsfiddle.net/markm/d3c2g42L/