2014/10/13

台灣地圖繪製和簡單應用 (使用d3js 和 g0v 提供的 twgeojson)

Environment Requirement: Node.js

Step 1. Clone project from https://github.com/g0v/twgeojson

本文撰寫時的版本為 d5ca193121689b1b9506b73c12fdd68f3c3e6881

Step 2. Install module


因為 package.json 被放在 json 資料夾下,所以要到裡面進行 npm install

twgeojson$ cd json
twgeojson/json$ npm install

接下來把產生的 node_modules 資料夾移到外面(為了要配合 make 設定)

twgeojson/json$ mv node_module ..

Step 3. Make

twgeojson$ make

這指令會自動從交通部網站上下載一些資料後用 mapshaper 轉換成 topojson 格式
可是載下來轉換成 topojson 的 twCounty2010.topo.json 其實內容是縣市合併前的資訊(打開會發現裡面有台北縣,但沒有新北市)>br/> 不過在 json 資料夾中有提供 twCounty2010.geo.json 這個檔案就是縣市合併後的資料了,共有 21 個縣市的資料,我們可以藉由 mapshaper 把他轉換成 topojson 來加快網頁顯示地圖的速度。
如須 clean,請使用 make clean-topo,小心不要 make clean !他會把 json 資料夾裡的 geoJSON 砍掉(這很重要,別亂砍!)


Step 4. 使用 mapshaper 轉換 geoJSON 為 topoJSON

twgeojson/json$ ../node_modules/.bin/mapshaper -p 0.01 twCounty2010.geo.json -f topojson --encoding utf-8 -o twCounty2010merge.topo.json

Step 5. 測試用d3js+topojson顯示地圖

<!DOCTYPE html>
<html lang="en">
 <head>
  <title></title>
  <style>
  #map {
   width: 960px;
   height: 500px;
  }
  </style>
 </head>
 <body>
  <svg id="map"></svg>
 </body>
 <script src="http://d3js.org/d3.v3.min.js"></script>
 <script src="http://d3js.org/topojson.v1.min.js"></script>
 <script>
 
 d3.json("../json/twCounty2010merge.topo.json", function (error, data) {

    topo = topojson.feature(data, data.objects.layer1);
  prj = d3.geo.mercator().center([120.979531, 23.978567]).scale(5000);

  path = d3.geo.path().projection(prj);

  locks = d3.select("svg#map").selectAll("path").data(topo.features).enter()
  .append("path").attr("d", path);
 });
 </script> 
</html>

Step 6. 顯示一些資料(以人口資料為例)

我們先從維基百科上面抓個資料試試看 http://zh.wikipedia.org/wiki/%E8%87%BA%E7%81%A3%E8%A1%8C%E6%94%BF%E5%8D%80%E4%BA%BA%E5%8F%A3%E5%88%97%E8%A1%A8

然後編成一個簡單的 json 檔案


[
  {
    "COUNTYNAME":"新北市",
    "population":3961374
  },
  {
    "COUNTYNAME":"高雄市",
    "population":2777461
  },
  {
    "COUNTYNAME":"臺中市",
    "population":2712948
  },
  {
    "COUNTYNAME":"臺北市",
    "population":2695649
  },
  {
    "COUNTYNAME":"桃園縣",
    "population":2054260
  },
  {
    "COUNTYNAME":"臺南市",
    "population":1883493
  },
  {
    "COUNTYNAME":"彰化縣",
    "population":1292126
  },
  {
    "COUNTYNAME":"屏東縣",
    "population":849326
  },
  {
    "COUNTYNAME":"雲林縣",
    "population":706688
  },
  {
    "COUNTYNAME":"苗栗縣",
    "population":566918
  },
  {
    "COUNTYNAME":"新竹縣",
    "population":536111
  },
  {
    "COUNTYNAME":"嘉義縣",
    "population":526028
  },
  {
    "COUNTYNAME":"南投縣",
    "population":515081
  },
  {
    "COUNTYNAME":"宜蘭縣",
    "population":458784
  },
  {
    "COUNTYNAME":"新竹市",
    "population":431029
  },
  {
    "COUNTYNAME":"基隆市",
    "population":373597
  },
  {
    "COUNTYNAME":"花蓮縣",
    "population":333531
  },
  {
    "COUNTYNAME":"嘉義市",
    "population":270885
  },
  {
    "COUNTYNAME":"臺東縣",
    "population":224931
  },
  {
    "COUNTYNAME":"金門縣",
    "population":126156
  },
  {
    "COUNTYNAME":"澎湖縣",
    "population":101482
  },
  {
    "COUNTYNAME":"連江縣",
    "population":12481
  }
]

用 COUNTYNAME 做對應

d3.json("population-2014-09.json", function (popData) { 

    var population = new Array();

    for(var i = 0, len = popData.length; i < len; i+=1) {
        population[popData[i].COUNTYNAME] = popData[i].population;
    }

    for(var i = 0, len = topo.features.length; i < len; i+=1) {
        topo.features[i].properties.value = population[topo.features[i].properties.name]
    }

    colorMap = d3.scale.linear().domain([0,5000000]).range(["#000","#f00"]);

    locks = d3.select("svg#map").selectAll("path").data(topo.features).enter().append("path").attr("fill",function(d){        return colorMap(d.properties.value); }).attr("d", path);    
}

如此一來就大功告成
參考資料:

2 comments: