2017-07-10 160 views
0

我想獲得一張世界地圖,顯示類似於這裏提供的美國地圖(U.S. map),但我遇到了一些問題。目前,這是我迄今爲止我的世界地圖代碼:d3.js world topojson v4

<!DOCTYPE html> 
<style> 

</style> 
<svg width="960" height="600"></svg> 
<script src="https://d3js.org/d3.v4.min.js"></script> 
<script src="https://d3js.org/topojson.v2.min.js"></script> 
<script> 

var svg = d3.select("svg"); 

var path = d3.geoPath(); 

d3.json("https://unpkg.com/[email protected]/world/50m.json", function(error, world) 
{ 
    if (error) throw error; 

    svg.append("g") 
     .selectAll("path") 
     .data(topojson.feature(world, world.objects.countries).features) 
     .enter().append("path") 
      .attr("d", path); 

}); 

</script> 

然而,它顯示只佔用了我的窗口的左上部分,而且似乎看不正確的地圖。 目前我對我可能做錯了什麼感到困惑。如果有人有任何見解,我將不勝感激。

謝謝。

編輯:實際上,我是能夠得到它提供的代碼在這裏工作

<!DOCTYPE html> 
<style> 

    .countries :hover 
    { 
     fill: red; 
    } 

    .country-borders 
    { 
     fill: none; 
     stroke: #FFF; 
     stroke-width: 0.5px; 
     stroke-linejoin: round; 
     stroke-linecap: round; 
     cursor: pointer; 

    } 

</style> 
<meta charset="utf-8"> 
<body> 
<script src="http://d3js.org/d3.v4.min.js"></script> 
<script src="http://d3js.org/topojson.v1.min.js"></script> 
<script> 
var format = d3.format(","); 


var margin = {top: 0, right: 0, bottom: 0, left: 0}, 
      width = 1200 - margin.left - margin.right, 
      height = 900 - margin.top - margin.bottom; 


var path = d3.geoPath(); 

var svg = d3.select("body") 
      .append("svg") 
      .attr("width", width) 
      .attr("height", height) 
      .append('g') 
      .attr('class', 'map'); 

var projection = d3.geoMercator() 
        .scale(170) 
        .translate([width/2, height/1.5]); 

var path = d3.geoPath().projection(projection); 


d3.json("https://unpkg.com/[email protected]/world/50m.json", function(error, world) 
{ 
    svg.append("g") 
     .attr("class", "countries") 
    .selectAll("path") 
     .data(topojson.feature(world, world.objects.countries).features) 
    .enter().append("path") 
     .attr("d", path); 


    svg.append("path") 
     .attr("class", "country-borders") 
     .attr("d", path(topojson.mesh(world, world.objects.countries, function(a, b) 
     { 
      return a !== b; 
     }))); 
}); 

</script> 
</body> 
</html> 

我相信我在做我的縮放錯誤,不能正確地做投影到地圖上。如果有人對我的做法有任何意見,請讓我知道。

回答

1

您引用的美國json是一個特殊的json文件 - 它不需要使用投影。您的path變量使用空投影(默認投影),將geojson中的座標(topojson轉換到的座標)轉換爲像素值而不進行轉換。

此文件可能已創建,允許通過跳過投影細節來顯示d3功能的更簡單的塊,但無論如何由於其投影方式而相對獨特。

該美國json文件中的每個頂點已經從表示三維地球上一個點的緯度/經度對轉換爲笛卡爾x,y座標,表示寬度爲960,高度爲500的平面bl.ock默認視圖的寬度和高度)。你的世界數據仍然包含緯度經度對,因此需要使用投影。

A給出你的數據未被投影的是它是顛倒的,這是在沒有定義投影的變換的情況下將緯度經度數據轉換爲svg中的像素座標時的結果。北極北緯90度,赤道0度。使用SVG時,y座標爲零將位於屏幕頂部,90的y座標將向下90像素。因此,將緯度經度點轉換爲x,y svg點時,北極將位於赤道以下,且不會轉換。此外,西半球和南半球的x值和/或y值都是負數,所以它們不會在沒有變換的情況下出現在你的svg中。這就是爲什麼你只能看到地圖上主要子午線以東和赤道以北的點。

如何解決這個問題?你需要投影你的數據。你可以使用任何一個預測,我會用墨卡託,因爲它很可能比其他人更容易識別(儘管兩極附近主要失真的問題):

var projection = d3.geoMercator(); 
var path = d3.geoPath().projection(projection); 

這就是它(see here)。

作爲參考,墨卡託投影的默認參數旨在顯示960像素的地球,如果您想要專注於特定區域或以不同大小(比例)顯示地圖,則需要設置投影參數。