D3-多年渲染'美国地图上的州数据价值
D3 - Rendering Multiple Years' Worth of State Data on US Map
我是编程新手,我一直在学习O'Reilly交互式数据可视化一书中的示例。
现在,我正在按州对5年的电动汽车数据进行可视化。每个州的颜色都会根据特定年份注册的电动汽车数量而变化。
问题:
每次我点击下拉菜单中的year
,它都会在下面创建另一个地图svg。我如何让它在同一个(现有的)地图svg上重新渲染数据?
背景:
我有定义svg维度的全局变量。我还有两个功能:
drawMap
有一个year参数,构建svg,将数据从csv加载到us_map.json
,并创建所有状态边界clickEventMap
将事件侦听器附加到每个年份按钮,然后调用drawMap
函数,该函数通过与按钮上的年份匹配的年份。最后,我调用drawMap(2013)
,使页面默认为2013数据,然后调用clickEventMap()
到目前为止我尝试了什么:
在d3 color.domain
方法之后的I CCD_。
此外,如果在调用drawMap()
时手动更改参数,则可以成功更改在现有映射上呈现的数据。
我的代码:
var w = 1200;
var h = 800;
var barpadding = 1;
var drawMap = function(year) {
var svg = d3.select("body")
.append("svg")
.attr("height", h)
.attr("width", w);
var projection = d3.geo.albersUsa()
.translate([w/2, h/2])
.scale([1600]);
var path = d3.geo.path()
.projection(projection);
var color = d3.scale.quantize()
.range(["rgb(237, 248, 233)", "rgb(186, 228, 179)", "rgb(116,196,118)", "rgb(49, 163, 84)", "rgb(0, 109, 44)"]);
color.domain([
d3.min(data, function(d) {return d["electric_vehicles_" + year];}),
d3.max(data, function(d) { return d["electric_vehicles_" + year];})
]);
console.log(year);
d3.json("us-states.json", function(json) {
for (var i = 0; i < data.length; i ++) {
var dataState = data[i].state;
var dataValue = parseFloat(data[i]["electric_vehicles_" + year]);
for (var j = 0; j < json.features.length; j++) {
var jsonState = json.features[j].properties.name;
if (dataState === jsonState) {
json.features[j].properties.value = dataValue;
break;
}
}
}
var stateView = function() {
console.log("State clicked.");
location.href="/states/1";
svg.selectAll("path")
.data(json.features)
.enter()
.append("path")
.attr("d", path)
.style("fill", function(d) {
var value = d.properties.value;
if (value) {
return color(value);
}
else {
return "#ccc";
}
})
.on("mouseover", function(d, i) {
d3.select(this)
.style("fill-opacity", 0.5);
})
.on("mouseout", function(d, i) {
d3.selectAll("path")
.style("fill-opacity", 1);
})
.on("click", function() {
stateView();
});
});
});
};
var clickEventMap = function() {
$("#map2013").on("click", function() {
// var year = 2013;
drawMap(2013);
});
$("#map2012").on("click", function() {
// var year = 2012;
drawMap(2012);
});
$("#map2011").on("click", function() {
// var year = 2011;
drawMap(2011);
});
$("#map2010").on("click", function() {
// var year = 2010;
drawMap(2010);
});
$("#map2009").on("click", function() {
// var year = 2009;
drawMap(2009);
});
};
drawMap(2013);
clickEventMap();
感谢您的意见。
您的主要问题是在drawMap
函数内部做得太多。很多事情只需要做一次,而不是每次换年。这就是为什么你会得到多个地图。每次调用drawMap
时,此代码都会创建一个新的svg
var svg = d3.select("body")
.append("svg")
.attr("height", h)
.attr("width", w);
如果你只是把它从drawMap
函数中上移,你只会得到一个svg。
每次绘制地图时,您还会得到"us states.json"文件。从技术上讲,这可能会起作用,但会导致很多你真正不需要的慢速网络请求。只需在页面加载时发出一次请求。这是对代码的一个相当大的重组更改,因为基本上之后的所有内容都需要从回调中调用。
最后,在您做出这些更改后,您将需要更改绘制状态的代码,以使它们正确更新。现在,您可以在"输入"选项上执行所有操作,该选项将仅在新路径上操作。由于您将编辑现有路径,您的代码需要看起来更像这样:
var paths = svg.selectAll("path")
.data(json.features)
.enter()
.append("path")
.attr("d", path)
.on("mouseover", function(d, i) {
d3.select(this)
.style("fill-opacity", 0.5);
})
.on("mouseout", function(d, i) {
d3.selectAll("path")
.style("fill-opacity", 1);
})
.on("click", function() {
stateView();
});
paths.style("fill", function(d) {
var value = d.properties.value;
if (value) {
return color(value);
} else {
return "#ccc";
}
});
Mike Bostocks的文章Thinking with Joins和Three Little Circles都是理解d3更新的好资源。
基本上,只要想想你只需要做一次什么,以及每次点击新的一年需要改变什么(更新你的色阶并为每个州设置填充样式)。试着把所有发生的事情都拉到一个init函数中,并保持drawMap
函数较小。
- 缓存谷歌地图数据
- 我的地图数据's不会使用php存储在mysql数据库中
- 优化地图数据
- 谷歌地图数据类型抛出类型错误:can't将未定义转换为对象
- 从外部网站获取谷歌地图数据
- 如何填充谷歌地图数据图层的颜色
- 使用滑块控制器更新地图数据/阴影?包括示例
- 有没有办法在向用户显示整个地图时隐藏数据库的地图数据
- 如何读取本地谷歌地图数据
- 如何防止IE8缓存OpenLayers地图数据(ASP.Net)
- AmMap -在更新地图数据后保持相同的缩放级别和位置
- 当我展开手风琴面板时,谷歌地图数据将不会出现
- D3地图数据标签没有正确显示
- Highmaps英国地图数据
- 使用$. getjson从JSON中加载地图数据
- 用Angularjs同步Leafletjs的地图数据
- 如何将事件附加到在TileMill中创建的自然地球地图数据
- 如何获得外部谷歌地图数据作为KML从HttpResponse直接到Javascript或jQuery
- Javascript:存储地图数据的最佳方式
- 从地图数据中删除特定多边形