交互式 d3 邮政编码等值线 - 华盛顿州
Interactive d3 zip code choropleth - WA state
正如标题所说,我正在尝试使用 d3 制作交互式等值线。我发现了一个有趣的例子,我正试图将其复制到另一个位置。
具体来说,我正在尝试在邮政编码级别绘制华盛顿州。
我添加了显示最终结果的 code I have at the moment that could be potentially edited, it's based on this example here is the live demo。
这适用于加利福尼亚州,但是当更改邮政编码 topojson 州(到华盛顿州)时,该图不起作用。也没有明显的错误。该错误可能与 topojson 的差异有关。
这是california topojson, here the Washington version。
下面是为每个 topojson 打印的第一个值。
California topojson:
{
"type": "Topology",
"objects": {
"zip": {
"type": "GeometryCollection",
"crs": {
"type": "name",
"properties": {
"name": "urn:ogc:def:crs:OGC:1.3:CRS84"
}
},
"geometries": [
{
"type": "Polygon",
"properties": {
"zipcode": 94601
},
"arcs": [
[
0,
1,
2,
3,
4,
5
]
]
}
华盛顿 topojson:
{
"type": "Topology",
"objects": {
"tl_2010_53_zcta510": {
"type": "GeometryCollection",
"crs": {
"type": "name",
"properties": {
"name": "urn:ogc:def:crs:OGC:1.3:CRS84"
}
},
"geometries": [
{
"type": "Polygon",
"properties": {
"zipcode": "98822"
},
"arcs": [
[
0,
1,
2,
3
],
[
4
]
]
}
下面是main.js
函数。我假设这一点并检查两个 topojson 文件可以帮助找到问题所在。基本上唯一改变的是 topojson 文件,然后 main.js
函数应该反映这些改变。
此外,"fake_data.csv" 将只表示一系列 zipcode:value 对:
zip,values
98001,1
98002,1
98003,1
98004,2
98005,2
98006,2
main.js
(function chart() {
var width = 1000,
height = 1200,
centered;
var rateById = d3.map();
var quantize = d3.scale.quantize()
.domain([0, 100000])
.range(d3.range(9).map(function(i) { return "q" + i + "-9"; }));
var projection = d3.geo.albersUsa()
.scale(6000)
.translate([2300, 680]);
var path = d3.geo.path()
.projection(projection);
var svg = d3.select("#ca-chart").append("svg")
.attr("width", width)
.attr("height", height);
var tooltip = d3.select("#ca-chart").append("div")
.attr("class", "tooltip")
.style("opacity", 0);
svg.append("rect")
.attr("class", "background")
.attr("width", width)
.attr("height", height)
.on("click", clicked);
var g = svg.append("g");
// These are the two lines that are different from the working example
queue()
.defer(d3.json, "https://gist.githubusercontent.com/martinbel/e14cd6ecd565914f53af/raw/e3a3a8332c20fe3cee6d7fd2a9ac01ad43f7aaa4/WA.topojson")
.defer(d3.csv, "fake_data.csv", function(d) { rateById.set(d.zip.toString(), +d.values); })
.await(ready);
function ready(error, zipcode) {
var features = topojson.feature(zipcode, zipcode.objects.tl_2010_53_zcta510).features;
g.append("g")
.attr("class", "state")
.selectAll("path")
.data(topojson.feature(zipcode, zipcode.objects.tl_2010_53_zcta510).features)
.enter().append("path")
.attr("d", path)
.attr("stroke", "#333")
.attr("stroke-width", "1.5px")
.attr("fill", "#fff");
g.append("g")
.attr("class", "zipcodes")
.selectAll("path")
.data(features)
.enter().append("path")
.attr("class", getColorClass)
.attr("d", path)
.on("click", clicked)
.on("mouseover", mouseover)
.on("mouseout", mouseout);
}
function getColorClass(d) {
return quantize(rateById.get(d.properties.zipcode));
}
function getPopulation(d) {
return rateById.get(getZip(d)).toString();
}
function getZip(d) {
return d && d.properties ? d.properties.zipcode : null;
}
function mouseout(d) {
d3.select(this)
.style("stroke", null);
tooltip.transition()
.duration(250)
.style("opacity", 0);
}
function mouseover(d) {
d3.select(this.parentNode.appendChild(this))
.style("stroke", "#F00");
tooltip.transition()
.duration(250)
.style("opacity", 1);
tooltip
.html("<p><strong>Zipcode: " + getZip(d) + "<br>Population: " + getPopulation(d) + "</strong></p>")
.style("left", (d3.event.pageX + 25) + "px")
.style("top", (d3.event.pageY - 28) + "px");
}
function clicked(d) {
var x, y, k;
if (d && centered !== d) {
var centroid = path.centroid(d);
x = centroid[0];
y = centroid[1];
k = 8; // control zoom depth
centered = d;
} else {
x = width / 2;
y = height / 2;
k = 1;
centered = null;
}
g.selectAll("path")
.classed("active", centered && function(d) { return d === centered; });
g.transition()
.duration(750)
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")scale(" + k + ")translate(" + -x + "," + -y + ")")
.style("stroke-width", 1.5 / k + "px");
}
d3.select(self.frameElement).style("height", height + "px");
}());
topojson 文件是通过以下方式生成的:
curl -O "ftp://ftp2.census.gov/geo/tiger/TIGER2010/ZCTA5/2010/tl_2010_53_zcta510.zip"
unzip "tl_2010_53_zcta510.zip"
ogr2ogr -f GeoJSON -s_srs crs:84 -t_srs crs:84 tl_2010_53_zcta510.geojson tl_2010_53_zcta510.shp
topojson -o tl_2010_53_zcta510.topojson --properties zipcode=ZCTA5CE10 tl_2010_53_zcta510.geojson
问题是您在活动查看区域之外绘制路径。将此作为您的 projection
尝试,您将看到路径。
var projection = d3.geo.albersUsa()
// .scale(6000)
// .translate([2300, 680]);
您必须为华盛顿编辑 scaling/translation...在执行此操作时可能有助于使您的 svg width
和 height
非常大(10000 像素左右)这样您就可以看到地图的最终位置。
这解决了显示地图和显示地图的问题,而无需手动修改参数。实际上,诀窍是使用支持 .center()
方法的投影,albersUsa
不支持。那么整理scale参数就简单多了
var projection = d3.geo.mercator()
.center([-120.574951, 47.361153])
.scale(5000)
.translate([(width) / 2, (height)/2]);
在此之后出现了一些其他问题。
正如标题所说,我正在尝试使用 d3 制作交互式等值线。我发现了一个有趣的例子,我正试图将其复制到另一个位置。 具体来说,我正在尝试在邮政编码级别绘制华盛顿州。
我添加了显示最终结果的 code I have at the moment that could be potentially edited, it's based on this example here is the live demo。
这适用于加利福尼亚州,但是当更改邮政编码 topojson 州(到华盛顿州)时,该图不起作用。也没有明显的错误。该错误可能与 topojson 的差异有关。
这是california topojson, here the Washington version。
下面是为每个 topojson 打印的第一个值。
California topojson:
{
"type": "Topology",
"objects": {
"zip": {
"type": "GeometryCollection",
"crs": {
"type": "name",
"properties": {
"name": "urn:ogc:def:crs:OGC:1.3:CRS84"
}
},
"geometries": [
{
"type": "Polygon",
"properties": {
"zipcode": 94601
},
"arcs": [
[
0,
1,
2,
3,
4,
5
]
]
}
华盛顿 topojson:
{
"type": "Topology",
"objects": {
"tl_2010_53_zcta510": {
"type": "GeometryCollection",
"crs": {
"type": "name",
"properties": {
"name": "urn:ogc:def:crs:OGC:1.3:CRS84"
}
},
"geometries": [
{
"type": "Polygon",
"properties": {
"zipcode": "98822"
},
"arcs": [
[
0,
1,
2,
3
],
[
4
]
]
}
下面是main.js
函数。我假设这一点并检查两个 topojson 文件可以帮助找到问题所在。基本上唯一改变的是 topojson 文件,然后 main.js
函数应该反映这些改变。
此外,"fake_data.csv" 将只表示一系列 zipcode:value 对:
zip,values
98001,1
98002,1
98003,1
98004,2
98005,2
98006,2
main.js
(function chart() {
var width = 1000,
height = 1200,
centered;
var rateById = d3.map();
var quantize = d3.scale.quantize()
.domain([0, 100000])
.range(d3.range(9).map(function(i) { return "q" + i + "-9"; }));
var projection = d3.geo.albersUsa()
.scale(6000)
.translate([2300, 680]);
var path = d3.geo.path()
.projection(projection);
var svg = d3.select("#ca-chart").append("svg")
.attr("width", width)
.attr("height", height);
var tooltip = d3.select("#ca-chart").append("div")
.attr("class", "tooltip")
.style("opacity", 0);
svg.append("rect")
.attr("class", "background")
.attr("width", width)
.attr("height", height)
.on("click", clicked);
var g = svg.append("g");
// These are the two lines that are different from the working example
queue()
.defer(d3.json, "https://gist.githubusercontent.com/martinbel/e14cd6ecd565914f53af/raw/e3a3a8332c20fe3cee6d7fd2a9ac01ad43f7aaa4/WA.topojson")
.defer(d3.csv, "fake_data.csv", function(d) { rateById.set(d.zip.toString(), +d.values); })
.await(ready);
function ready(error, zipcode) {
var features = topojson.feature(zipcode, zipcode.objects.tl_2010_53_zcta510).features;
g.append("g")
.attr("class", "state")
.selectAll("path")
.data(topojson.feature(zipcode, zipcode.objects.tl_2010_53_zcta510).features)
.enter().append("path")
.attr("d", path)
.attr("stroke", "#333")
.attr("stroke-width", "1.5px")
.attr("fill", "#fff");
g.append("g")
.attr("class", "zipcodes")
.selectAll("path")
.data(features)
.enter().append("path")
.attr("class", getColorClass)
.attr("d", path)
.on("click", clicked)
.on("mouseover", mouseover)
.on("mouseout", mouseout);
}
function getColorClass(d) {
return quantize(rateById.get(d.properties.zipcode));
}
function getPopulation(d) {
return rateById.get(getZip(d)).toString();
}
function getZip(d) {
return d && d.properties ? d.properties.zipcode : null;
}
function mouseout(d) {
d3.select(this)
.style("stroke", null);
tooltip.transition()
.duration(250)
.style("opacity", 0);
}
function mouseover(d) {
d3.select(this.parentNode.appendChild(this))
.style("stroke", "#F00");
tooltip.transition()
.duration(250)
.style("opacity", 1);
tooltip
.html("<p><strong>Zipcode: " + getZip(d) + "<br>Population: " + getPopulation(d) + "</strong></p>")
.style("left", (d3.event.pageX + 25) + "px")
.style("top", (d3.event.pageY - 28) + "px");
}
function clicked(d) {
var x, y, k;
if (d && centered !== d) {
var centroid = path.centroid(d);
x = centroid[0];
y = centroid[1];
k = 8; // control zoom depth
centered = d;
} else {
x = width / 2;
y = height / 2;
k = 1;
centered = null;
}
g.selectAll("path")
.classed("active", centered && function(d) { return d === centered; });
g.transition()
.duration(750)
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")scale(" + k + ")translate(" + -x + "," + -y + ")")
.style("stroke-width", 1.5 / k + "px");
}
d3.select(self.frameElement).style("height", height + "px");
}());
topojson 文件是通过以下方式生成的:
curl -O "ftp://ftp2.census.gov/geo/tiger/TIGER2010/ZCTA5/2010/tl_2010_53_zcta510.zip"
unzip "tl_2010_53_zcta510.zip"
ogr2ogr -f GeoJSON -s_srs crs:84 -t_srs crs:84 tl_2010_53_zcta510.geojson tl_2010_53_zcta510.shp
topojson -o tl_2010_53_zcta510.topojson --properties zipcode=ZCTA5CE10 tl_2010_53_zcta510.geojson
问题是您在活动查看区域之外绘制路径。将此作为您的 projection
尝试,您将看到路径。
var projection = d3.geo.albersUsa()
// .scale(6000)
// .translate([2300, 680]);
您必须为华盛顿编辑 scaling/translation...在执行此操作时可能有助于使您的 svg width
和 height
非常大(10000 像素左右)这样您就可以看到地图的最终位置。
这解决了显示地图和显示地图的问题,而无需手动修改参数。实际上,诀窍是使用支持 .center()
方法的投影,albersUsa
不支持。那么整理scale参数就简单多了
var projection = d3.geo.mercator()
.center([-120.574951, 47.361153])
.scale(5000)
.translate([(width) / 2, (height)/2]);
在此之后出现了一些其他问题。