【发布时间】:2017-11-19 19:48:28
【问题描述】:
我用 d3.js 创建了一个小的倍数地图。每个倍数都是一个不同的国家,在我的 csv 中被标记为出口商。我有 11 个出口国:加拿大、俄罗斯、美国、意大利、法国、英国、巴西、中国、印度、德国和日本。
我想填写每个国家/地区,但前提是它是代表倍数的国家/地区。因此,每个倍数只填充一个国家/地区。
你可以在这里查看我的块。倍数的国家(出口国)是线汇合的地方:https://bl.ocks.org/JulienAssouline/f899e2d6927aea6be65a109854b6f88a
现在我只为每个倍数填充了美国。我用这段代码填充了它:
svg.selectAll(".country")
.data(countries)
.enter()
.append("path")
.attr("class", "country")
.attr("fill", function(d){
if(d.properties.name == "United States"){
return "red"
} else {
return "#eeedeb"
}
})
.attr("d", path)
.attr("opacity", function(d){
if(d.properties.name == "United States"){
return 0.4
} else {
return 1
}
})
这显然是错误的,但我不确定如何按倍数填写每个出口国。
这是我所有的代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>D3: Loading TopoJSON data and generating SVG paths</title>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="//d3js.org/topojson.v1.min.js"></script>
<style type="text/css">
/* No style rules here yet */
body,html{
margin: 0;
padding: 0;
font-family: "Arial", sans-serif;
font-size: 11px;
text-align: center;
}
#chart{
background-color: white;
stroke-width: 1;
}
.country{
stroke: white;
stroke-width: 0.1;
}
</style>
</head>
<body>
<script type="text/javascript">
//Width and height
var w = 450;
var h = 800;
var margin = {
top: 10,
bottom: 0,
left: 0,
right: 30
};
var width = w - margin.left - margin.right;
var height = h - margin.top - margin.bottom;
var lineScale = d3.scaleSqrt()
.domain([0, 332])
.range([0.5, 3])
var circleScale = d3.scaleSqrt()
.domain([0, 4445])
.range([0.5, 10])
// define map projection
var projection = d3.geoAzimuthalEquidistant()
.translate([w/2, h/2 - 150])
.scale(100)
// .scale([500]);
//Define default path generator
var path = d3.geoPath()
.projection(projection)
// var svg = d3.select("body")
// .append("svg")
// .attr("id", "chart")
// .attr("width", w)
// .attr("height", h)
// .append("g")
// .attr("transform", "translate(0" + margin.left + "," + margin.top + ")");
d3.json("world.topojson", function(json){
d3.csv("arms_transfer_2012_2016.csv", function(error, data){
// data.forEach(function(d){
// d.Lon_Residence = +d.Lon_Residence
// d.Lat_Residence = +d.Lat_Residence
// })
var countries = topojson.feature(json, json.objects.countries).features
var Exporters = d3.nest()
.key(function(d){ return d.Exporter; })
.entries(data)
console.log(Exporters)
var svg = d3.select("body")
.selectAll("svg")
.data(Exporters)
.enter()
.append("svg")
.attr("id", "maps")
.attr("width", w)
.attr("height", h)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
svg.selectAll(".country")
.data(countries)
.enter()
.append("path")
.attr("class", "country")
.attr("fill", function(d){
if(d.properties.name == "United States"){
return "red"
} else {
return "#eeedeb"
}
})
.attr("d", path)
.attr("opacity", function(d){
if(d.properties.name == "United States"){
return 0.4
} else {
return 1
}
})
svg.selectAll("circles")
.data(function(d){ return d.values })
.enter()
.append("circle")
.attr("class", "importer")
.attr("r", function(d){
return circleScale(d.Millions)
})
.attr("cx", function(d){
var coords = projection([d.Longitude_imp, d.Latitude_imp])
return coords[0];
})
.attr("cy", function(d){
var coords = projection([d.Longitude_imp, d.Latitude_imp])
return coords[1];
})
.style("fill", function(d){
if(d.Millions > 20){
return "#cd0d0e"
} else {
return "none"
}
})
svg.selectAll(".arcs")
.data(function(d){ return d.values})
.enter()
.append("path")
.style("stroke", function(d){
if(d.Millions > 20){
return "#cd0d0e"
}
})
.attr("d", function(d){
return lngLatToArc(d, 1)
})
.style("fill", "none")
.style("opacity", 0.5)
.style("stroke-width", "0.5px")
svg.append("text")
.attr("x", 100)
.attr("y", 100)
.text(function(d){
return d.Exporter
})
function lngLatToArc(d, bend){
// If no bend is supplied, then do the plain square root
bend = bend || 1;
// `[d.Lon_Origin, d.Lat_Origin]` and `[d.Lon_Residence, d.Lat_Residence]` are arrays of `[lng, lat]`
// Note, people often put these in lat then lng, but mathematically we want x then y which is `lng,lat`
var sourceLngLat = [d.Longitude_exp, d.Latitude_exp],
targetLngLat = [d.Longitude_imp, d.Latitude_imp];
if(targetLngLat && sourceLngLat){
var sourceXY = projection(sourceLngLat),
targetXY = projection(targetLngLat);
// Uncomment this for testing, useful to see if you have any null lng/lat values
// if (!targetXY) console.log(d, targetLngLat, targetXY)
var sourceX = sourceXY[0],
sourceY = sourceXY[1];
var targetX = targetXY[0],
targetY = targetXY[1];
var dx = targetX - sourceX,
dy = targetY - sourceY
dr = Math.sqrt(dx * dx + dy * dy) * bend;
// To avoid a whirlpool effect, make the bend direction consistent regardless of whether the source is east or west of the target
var west_of_source = (targetX - sourceX) < 0;
if (west_of_source) return "M" + targetX + "," + targetY + "A" + dr + "," + dr + " 0 0,1 " + sourceX + "," + sourceY;
return "M" + sourceX + "," + sourceY + "A" + dr + "," + dr + " 0 0,1 " + targetX + "," + targetY;
} else{
return "M0,0,l0,0z";
}
}
})
})
</script>
</body>
</html>
我的数据以及我使用的 Topojson 文件可以在我的公共要点中找到:https://gist.github.com/JulienAssouline/f899e2d6927aea6be65a109854b6f88a
【问题讨论】:
标签: javascript d3.js maps