我对D3或javascript不太了解-我对所有这些都很陌生。我一直在忙于复制this的项目,实际上我一直是直接从中借来创建代码的。我希望制作一个可以根据访问者信息量更改我的数据的制图。我为自己的数据切换了很多变量,但收到一条错误消息:
d3.v2.min.js:2 Uncaught TypeError: Cannot read property 'length' of undefined
at n (d3.v2.min.js:2)
at Array.ks.data (d3.v2.min.js:2)
at (index):140
它在第一行标记错误
zone.data(carto_features)
.select("title")
.text(function (d) {
return d.properties.ZONE;
});
带有地图的svg显示得很好,它是根据访问者人口数据(在csv中存储为.YTD的)进行大小调整的。我相当确定我的json是一个topojson,我经过了整个过程来制作它一个基于以前的实现,并且其中的代码排列看起来是正确的。我确实在JSON中有一个名为ZONE的列,在我的csv名称区域中有一个列-但我认为,由于js区分大小写,所以这不是问题。
我尝试切换一些内容-这是我的代码。我将原始代码中注释掉的部分包括在内,以提供一些上下文。
<html>
<head>
<title>Gate Cartogram V2</title>
<meta charset="utf-8">
<script src="lib/d3.v2.min.js"></script>
<script src="lib/topojson.js"></script>
<script src="lib/cartogram.js"></script>
<link href='http://fonts.googleapis.com/css?family=Open+Sans:300' rel='stylesheet' type='text/css'>
<style type="text/css">
body {
font-family:'Open Sans', sans-serif;
font-weight: 300;
font-size: 14px;
line-height: 1.4em;
padding-top: 20px;
margin: 0 auto;
width: 600px;
}
#map-container {
height: 500px;
position: relative;
margin: 10px 0;
}
#map {
overflow: visible;
}
#click_to_run {
color:#888;
width: 600px;
font-size: 2em;
text-align: center;
cursor: pointer;
padding-top: 30px;
}
path.zones {
stroke: #AAA;
stroke-width: .5;
}
path.zones:hover {
stroke: #000;
}
</style>
</head>
<body>
<div id="click_to_run"
onclick="do_update()" >
...
</div>
<div id="map-container">
<svg id="map"></svg>
</div>
<script>
//the colour scheme for the different winning parties.
// var colour_map = {
// "ANC": "#FFCC00",
// "DA": "#005CA7",
// "IFP": "#FF1800"
// };
var map = d3.select("#map");
var zone = map.append("g")
.attr("id", "zone")
.selectAll("path");
var proj = d3.geo.albers()
.origin([-73.94,40.70])
.scale(50000);
var topology,
geometries,
carto_features;
var park_data = d3.map();
var carto = d3.cartogram()
.projection(proj)
.properties(function (d) {
// this add the "properties" properties to the geometries
return d.properties;
});
// the data came from some rolling up of info I got from iec.org.za site.
// It lists the winning party, number or registered voters and votes
// cast per local municipality.
d3.csv("data/park_2017.csv", function (data) {
data.forEach(function (d) {
park_data.set(d.ZONE, d.YTD);
})
});
// this loads test the topojson file and creates the map.
d3.json("data/GATE_V5.topojson", function (data) {
topology = data;
geometries = topology.objects.GATE_v5.geometries;
//these 2 below create the map and are based on the topojson implementation
var features = carto.features(topology, geometries),
path = d3.geo.path()
.projection(proj);
zone = zone.data(features)
.enter()
.append("path")
.attr("class", "zone")
.attr("id", function (d) {
return d.properties.ZONE;
})
.attr("d", path);
d3.select("#click_to_run").text("click here to run");
});
function do_update() {
d3.select("#click_to_run").text("thinking...");
setTimeout(function () {
// this sets the value to use for scaling, per munic. Here I used the total number
// of voters per munic. the scaling is relative to the max value.
carto.value(function (d) {
return +park_data.get(d.properties["ZONE"])[1];
});
if (carto_features == undefined)
//this regenrates the topology features for the new map based on
// carto_features = carto(topology, geometries).features;
//update the map data
zone.data(carto_features)
.select("title")
.text(function (d) {
return d.properties.ZONE;
});
zones.transition()
.duration(750)
.each("end", function () {
d3.select("#click_to_run").text("done")
})
.attr("d", carto.path);
}, 10);
}
</script>
</body>
</html>