【发布时间】:2016-01-29 17:02:17
【问题描述】:
我对 D3 还很陌生,遇到了一个问题。
我创建了一个简单的示例来说明我想要实现的目标。
首先,我有一个包含数据的 CSV 文件。在此示例中,它包含 2 家商店的某些流行手机几个月的手机销售数据。数据如下:
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>
我在 CSV 文件中读取的位置,然后使用 D3 嵌套创建了如下所示的层次结构:
商店->产品->月份->销售
我希望图表按月显示伦敦的每个产品的销售数据,然后如果更改选择,则按月显示格拉斯哥的销售数据。
但是,虽然显示的是伦敦数据,但当我选择格拉斯哥时,图表并未更新。
为了排除任何过于明显的情况,我对每个商店的数组索引进行了硬编码。
我还添加了 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); });
非常感谢您对改进或简化代码的任何其他建议。
【问题讨论】:
标签: javascript d3.js