D3js没有正确地将经度/纬度点投射到topojson地图上

时间:2018-03-14 15:01:37

标签: javascript d3.js data-visualization topojson

我使用topojson绘制带有D3js的世界地图。我相信这很好用。但是,当我尝试将纬度/经度点投影到地图上时,投影功能正在返回" NaN"对于具有负值的点,对正在工作的点的投影远离国家/地区在世界地图上的位置。

这是我读过的数据: 资产/数据/ gcf.csv

Coords,Country,Frequency
"[38.9597594, 34.9249653]",Turkey,1
"[61.0666922, -107.9917071]",Canada,3
"[52.5001698, 5.7480821]",Netherlands,1
"[42.6384261, 12.674297]",Italy,1
"[39.7837304, -100.4458825]",United States,69
"[59.6749712, 14.5208584]",Sweden,1
"[35.000074, 104.999927]",China,5
"[64.6863136, 97.7453061]",Russian Federation,2
"[36.5748441, 139.2394179]",Japan,1

的index.html

<div id="worldmap"></div>
<script src="../assets/js/graphs/map.js"></script>

资产/ JS /图形/ map.js

var width = 960;
var height = 500;

// set projection
var projection = d3.geo.mercator();

// create path variable
var path = d3.geo.path()
.projection(projection); 

// Define the div for the tooltip
var div = d3.select("body").append("div")   
.attr("class", "tooltip")               
.style("opacity", 0);

d3.json("https://unpkg.com/world-atlas@1/world/110m.json", function(error1, topo) {
if(error1) console.log("Error: topo json not loaded.");
d3.csv("../assets/data/gcf.csv", function(error2, data) {
if(error2) console.log("Error: Coord/frequency data not loaded.");

countries = topojson.feature(topo, topo.objects.countries).features;

projection
.scale(width / 2 / Math.PI)
.translate([(width / 2)-30, (height / 2)+50]);

data.forEach(function(d) {      
// + symbol convert from string representation of a number to an actual number
d.Frequency = +d.Frequency;
d.Coords = d.Coords.replace(/[\[\]"]+/g, '');
d.Coords = d.Coords.split(',');
d.Coords = d.Coords.map(x => parseFloat(x));
d.Country = d.Country;
console.log("Country:", d.Country, ". Projection: ", projection(d.Coords)[0], projection(d.Coords)[1]);
});

// create svg variable
var svg = d3.select("#worldmap").append("svg")
.attr("width", width)
.attr("height", height);

svg.append("rect")
.attr("width", "100%")
.attr("height","100%")
.attr("fill","#A2E8E8");

// add countries from topojson
svg.selectAll("path")
.data(countries).enter()
.append("path")
.attr("class", "feature")
.style("fill", "#71945A")
.attr("d", path);

// put boarder around countries 
svg.append("path")
.datum(topojson.mesh(topo, topo.objects.countries, function(a, b) { return a !== b; }))
.attr("class", "mesh")
.attr("d", path);
aa = [38.9597594, 34.9249653];


// add circles to svg
svg.selectAll("circle")
.data(data).enter()
.append("circle")
.attr("r", function(d) {
return d.Frequency === 1 ? d.Frequency* 10 : d.Frequency / 2
})
.attr("transform", function(d) {
return "translate(" + projection([
  (d.Coords[0]),
  (d.Coords[1])
]) + ")";
})
.attr("fill", "red")
.on("mouseover", function(d) {      
div.transition()        
.duration(200)      
.style("opacity", .9);      
div .html(d.Country)    
.style("left", (d3.event.pageX) + "px")     
.style("top", (d3.event.pageY - 28) + "px");    
})                  
.on("mouseout", function(d) {       
div.transition()        
.duration(500)      
.style("opacity", 0);   
});         
});
});

世界地图样式:

.feature {
fill: none;
stroke: grey;
stroke-width: 1px;
stroke-linejoin: round;
}

.mesh {
fill: none;
stroke: black;
stroke-width: 2px;
stroke-linejoin: round;
}

1 个答案:

答案 0 :(得分:1)

您的纬度和经度相反 - d3 geoProjection采用[x,y]或[long,lat]格式的坐标。您正在为投影提供[lat,long]数组,但如果您切换下面的代码:

.attr("transform", function(d) { 
    return "translate(" + projection([d.Coords[0],d.Coords[1]]) + ")";
})

要:

.attr("transform", function(d) { 
    return "translate(" + projection([d.Coords[1],d.Coords[0]]) + ")";
})

您将获得所需的地图:

enter image description here