[菜鳥工程師筆記] D3 js 配合QGIS處理泰國資料畫出點座標

郭佩禎
小郭 เจน
Published in
7 min readDec 16, 2019

D3 可以用來畫地圖,做資料視覺化,但是地圖的處理須要經過一些複雜的程序,有一些地圖知識,才能順利做出來,而查詢到的資料大部分都是台灣地圖的製作,但我這個泰國迷就是想要做泰國的地圖嘛,所以今天帶大家來實作泰國的資料。

先前準備

QGIS : 一個處理地圖的應用程式,到他的官網下載安裝(版本3)。

分為三大步驟: 資料蒐集、資料處理(QGIS)、資料呈現(D3)。

1. 資料蒐集

地圖的座標資料會儲存在.shp的檔案裡面,如果你要找到不同語系的data,就可以用該語言搜尋,台灣的資料可以在政府公開資料平台找到,點一下shp下載下來,而我使用的泰國資料在BANGKOKGIS裡面。解壓縮之後,有幾個檔案副檔名名稱: ,shp,shx, dbf, ,cpg pri,sbn,sbx,稍微認識一下這些資料:

必要檔案

這三個是打開地圖的必要資料!

.shp — 是美國環境系統研究所公司(ESRI)開發的空間資料,可以用來描述點point、線line、多邊形polygen等資料。

.shx — 圖形索引格式。幾何體位置索引,記錄每一個幾何體在shp檔案之中的位置,能夠加快向前或向後搜尋一個幾何體的效率。

.dbf — 屬性資料格式,以dBase III+ 的資料表格式儲存每個幾何形狀的屬性資料,有些圖形上面有資訊,座標、名稱,就是存在這裡。

非必要檔案

.prj — 投影格式,用於儲存地理坐標系統與投影資訊,包含了幾何資料所使用的經緯度坐標系統。

.cpg — 用於描述.dbf檔案的頁碼,指明其使用的字元編碼,當你使用資料是不同語系的時候,就需要這個檔案。

.sbn,. sbx — Shapefile空間索引格式,這是一個二進位的空間索引檔案,僅僅可以應用在ESRI的軟體之中。不是必須的,因為.shp檔案之中已經包含了所有的解析空間資料所需的資訊。

2. QGIS資料轉換

接下來,由於D3需要的是geojson(地圖專用的json資料)格式,所以我們必須要把shp轉換成geojson(使用經緯度),可以利用mapshaper 做轉換,把檔案拉進去匯出檔案格式即可,不過有些資料沒有辦法,就需要利用強大的qgis做資料處理。

打開安裝好的QGIS,選擇上方 圖層->加入圖層->加入向量圖層,選擇你的shp檔案,編碼的地方很重要! 國外的資料要去查看看該語系編碼是多少,泰國的資料可以用cp874,按下加入。

接著地圖就會出來了! 看到左邊的圖層已經加入了捷運站的點!

點擊左方圖層bts_station右鍵,開啟屬性表格,可以看到除了座標資料的name、location等資料(存在.dbf),如果剛剛沒有轉換cpg的話,這裡會是亂碼喔! 確認正常顯示後就可以先將屬性表格關起來。

在頁面下方的資訊,可以看到奇怪的座標值,以及EPSG32647。

EPSG是European Petroleum Survey Group的縮寫,EPSG定義了世界各國投影、坐標系統,所以不同的數值表不同的投影系統。我們必須把檔案轉換常見的經緯度數值EPSG:4326。

EPSG:4326是WGS84大地基準(Google Earth),是一般的經緯度數值。

也就是說,把EPSG32647àEPSG4326,並存成geojson檔。

所以我們按下圖層右鍵,匯出 → save feature as,格式選擇geojson,命名檔案名稱,crs坐標參考系統選擇4326,按下ok後就匯出了。

利用編輯器打開geojson檔案,確保檔案有找到正常的經緯度值。

3. D3.js作呈現

經過前面繁瑣的資料處理後,接著來到重頭戲了! 準備好geojson檔案後,開啟一個js file。

這裡用截圖想讓大家好看一點,附上程式碼在後面~

登登~出現囉~

這樣就利用d3把點座標畫出來囉!

const width = ‘600’const height = ‘400’// 讓d3抓svg,並寫入寬高var svg = d3.select(‘#svg’).attr(‘width’, width).attr(‘height’, height).attr(‘viewBox’, `0 0 ${width} ${height}`);console.log(svg)// 定義投影的資料var projection = d3.geo.mercator() // 利用麥卡托投影mercator(),.translate([width / 2, height / 2]) // translate把中心偏移量調整回來,.center([100.53, 13.74]) // center以該經緯度作為中心點(可以參考geojson裡面的座標值),.scale(122600); // scale要自己去調整,我使用的是捷運站資料,所以放大的倍數很大。// 座標變換函式var path = d3.geo.path().projection(projection);// 讓d3抓GeoJSON檔,並寫入path的路徑 bts_stationvar url = ‘../data/transBTS.geojson’; // GeoJSON的檔案路徑d3.json(url, (error, geometry) => {if (error) throw error;//插入分组元素var location = svg.selectAll(“.location”).data(geometry.features).enter().append(“g”).attr(“class”, “location”).attr(“transform”, function (d) {//计算标注点的位置var coor = projection([d.geometry.coordinates[0], d.geometry.coordinates[1]]);return “translate(“ + coor[0] + “,” + coor[1] + “)”;});location.append(“circle”).attr(“r”, 5).attr(“fill”, “#E91E63”).attr(“class”, “location”);});

--

--

郭佩禎
小郭 เจน

要在隨波逐流中飄到一個自己的島嶼。這裡記錄人生發生了甚麼。