Как следует из названия, я пытаюсь сделать интерактивную хороплет, используя d3. Я нашел интересный пример, который пытаюсь воспроизвести в другом месте. Конкретно, я пытаюсь изобразить штат Вашингтон на уровне почтового индекса.
Я добавил код, который у меня есть на данный момент, который потенциально может быть отредактирован, он основан на этом пример вот живой демонстрация, показывающая окончательный результат.
Это работает для штата Калифорния, однако при смене почтового индекса штата (на штат Вашингтон) сюжет не работает. Также нет явных ошибок. Ошибка могла быть в различиях в топожсоне.
Это калифорнийский топожсон, здесь Вашингтонская версия.
Ниже приведены первые значения, красиво напечатанные для каждого топографа.
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
]
]
}
Вашингтон топожсон:
{
"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