我对D3很新,并且遇到问题。在更新D3.js多行图表时遇到问题
我创建了一个我试图实现的简单示例。
首先,我有一个带有数据的CSV文件。在这个例子中,它包含了一些流行手机的电话销售数据,用于两家商店的数月。的数据如下所示:
Store,Product,Month,Sold
London,iPhone,0,5
London,iPhone,1,4
London,iPhone,2,3
London,iPhone,3,5
London,iPhone,4,6
London,iPhone,5,7
London,Android Phone,0,3
London,Android Phone,1,4
London,Android Phone,2,5
London,Android Phone,3,7
London,Android Phone,4,8
London,Android Phone,5,9
London,Windows Phone,0,1
London,Windows Phone,1,2
London,Windows Phone,2,6
London,Windows Phone,3,7
London,Windows Phone,4,8
London,Windows Phone,5,5
Glasgow,iPhone,0,3
Glasgow,iPhone,1,4
Glasgow,iPhone,2,5
Glasgow,iPhone,3,2
Glasgow,iPhone,4,1
Glasgow,iPhone,5,3
Glasgow,Android Phone,0,4
Glasgow,Android Phone,1,3
Glasgow,Android Phone,2,7
Glasgow,Android Phone,3,4
Glasgow,Android Phone,4,3
Glasgow,Android Phone,5,6
Glasgow,Windows Phone,0,3
Glasgow,Windows Phone,1,6
Glasgow,Windows Phone,2,7
Glasgow,Windows Phone,3,5
Glasgow,Windows Phone,4,3
Glasgow,Windows Phone,5,4
我写下面的代码在JS/D3.js:
<!DOCTYPE html>
<meta charset="utf-8">
<style>
svg {
font: 10px sans-serif;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.x.axis path {
fill:none;
stroke:#000;
shape-rendering: crispEdges;
}
.line {
fill: none;
stroke-width: 1.5px;
}
</style>
<body>
<p id="menu"><b>Test</b>
<br>Select Store:
<select>
<option value="0">London</option>
<option value="1">Glasgow</option>
</select>
</p>
<script src="http://d3js.org/d3.v3.js"></script>
<script>
var margin = {top: 20, right: 80, bottom: 30, left: 50},
width = 900 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
// construct a linear scale for x axis
var x = d3.scale.linear()
.range([0,width]);
// construct a linear scale for y axis
var y = d3.scale.linear()
.range([height,0]);
// use the default line colours (see http://stackoverflow.com/questions/21208031/how-to-customize-the-color-scale-in-a-d3-line-chart for info on setting colours per line)
var color = d3.scale.category10();
// create the x axis and orient of ticks and labels at the bottom
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
// create the y axis and orient of ticks and labels on the left
var yAxis = d3.svg.axis()
.scale(y)
.orient("left");
// line generator function
var line = d3.svg.line()
//.interpolate("basis")
.x(function(d) { return x(d.Month); })
.y(function(d) { return y(d.Sold); });
var svg = d3.select("body").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
d3.csv("sampleData.csv", function(error, data) {
color.domain(d3.keys(data[0]).filter(function(key) { return key == "Product"; }));
// first we need to corerce the data into the right formats
// map the data from the CSV file
data = data.map(function (d) {
return {
Store: d.Store,
Product: d.Product,
Month: +d.Month,
Sold: +d.Sold };
});
// nest the data by regime and then CI
var salesDataByStoreProduct = d3.nest()
.key(function(d) { return d.Store; })
.key(function(d) { return d.Product; })
.entries(data);
// get the first regime's nest
var salesDataForLondon;
salesDataForLondon = salesDataByStoreProduct[0].values;
console.log(salesDataForLondon);
x.domain([d3.min(salesDataForLondon, function(d) { return d3.min(d.values, function (d) { return d.Month; }); }),
d3.max(salesDataForLondon, function(d) { return d3.max(d.values, function (d) { return d.Month; }); })]);
y.domain([0, d3.max(salesDataForLondon, function(d) { return d3.max(d.values, function (d) { return d.Sold; }); })]);
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.append("g")
.attr("class", "y axis")
.call(yAxis);
var Products = svg.selectAll(".Product")
.data(salesDataForLondon, function(d) { return d.key; })
.enter().append("g")
.attr("class", "Product");
Products.append("path")
.attr("class", "line")
.attr("d", function(d) { return line(d.values); })
.style("stroke", function(d) { return color(d.key); });
function redraw()
{
var salesDataByStoreProduct = d3.nest()
.key(function(d) { return d.Store; })
.key(function(d) { return d.Product; })
.entries(data);
var salesDataForGlasgow;
salesDataForGlasgow = salesDataByStoreProduct[1].values;
console.log(salesDataForGlasgow);
x.domain([d3.min(salesDataForGlasgow, function(d) { return d3.min(d.values, function (d) { return d.Product; }); }),
d3.max(salesDataForGlasgow, function(d) { return d3.max(d.values, function (d) { return d.Product; }); })]);
y.domain([0, d3.max(salesDataForGlasgow, function(d) { return d3.max(d.values, function (d) { return d.Sales; }); })]);
svg.select("g")
.call(xAxis);
svg.select("g")
.call(yAxis);
var Products = svg.selectAll(".Product")
.data(salesDataForGlasgow, function(d) { return d.key; })
.enter().select("g")
.attr("class", "Product");
Products.select("path")
.attr("d", function(d) { return line(d.values); })
.style("stroke", function(d) { return color(d.key); });
}
/******************************************************/
var menu = d3.select("#menu select")
.on("change", change);
function change()
{
clearTimeout(timeout);
d3.transition()
.duration(altKey ? 7500 : 1500);
redraw();
}
var timeout = setTimeout(function() {
menu.property("value", "ENEUSE").node().focus();
change();
}, 7000);
var altKey;
d3.select(window)
.on("keydown", function() { altKey = d3.event.altKey; })
.on("keyup", function() { altKey = false; });
/******************************************************/
});
</script>
</body>
</html>
其中I在CSV文件已经阅读并然后用于D3巢创建如下图所示的层级:
Store->产品 - >月 - >销售
我希望图表按月伦敦,然后如果选择改变时,显示本单位产品的销售数据周一的销售数据为格拉斯哥。
但是,尽管伦敦数据正在呈现,但我选择格拉斯哥时图表并未更新。
要排除任何太明显的事情,我已经硬编码了每个商店的数组索引。
我也添加了console.log,并且可以看到正在使用的正确数据,但是只有在调用redraw()时才在图表中呈现。
我会很感激的,我怀疑这涉及到下面的代码问题的原因的任何建议:
var Products = svg.selectAll(".Product")
.data(salesDataForGlasgow, function(d) { return d.key; })
.enter().select("g")
.attr("class", "Product");
Products.select("path")
.attr("d", function(d) { return line(d.values); })
.style("stroke", function(d) { return color(d.key); });
改善或简化了代码任何其他意见将非常感激地赞赏。
非常感谢卢克。结合Mark的代码,我已经能够解决这个问题。我将重新发布工作代码。 –