Loading and parsing TOPOJSON
導入Topojson
d3文件
地址:https://unpkg.com/topojson@3.0.2/dist/topojson.min.js
想要找d3文件的話去unpkg.com好像大部分都能找到的樣子
Rendering geographic features
尋找合適的地圖數據:谷歌搜索world-atlas npm
,第一個網站點進去,然后選擇合適的d3文件。
這個文件里面的地圖是Topojson
格式的,想要轉化為geojson
需要使用topojson
中的feature
函數,傳入兩個參數,例如:
json('https://cdn.jsdelivr.net/npm/world-atlas@2/countries-110m.json').then(data => { const countries = feature(data, data.objects.countries);console.log(countries); }
然后就可以使用數據,給每個數據添加path
,然后通過設置屬性d
進行繪制
Using different map projections
圖形的不同關鍵就在繪制d
的函數的不同。
d3
官網上有許多繪制不同形狀地圖的函數,可以根據需要選擇自己喜歡的。
網址:https://github.com/d3/d3-geo-projection
這里選擇的是geoEqualEarth
,這個函數需要從d3文件中導入。于此同時還需要導入geoPath
函數
const projection = geoEqualEarth();
const pathGenerator = geoPath().projection(projection);json('https://cdn.jsdelivr.net/npm/world-atlas@2/countries-110m.json').then(data => { const countries = feature(data, data.objects.countries);console.log(countries); svg.selectAll('path').data(countries.features).enter().append('path').attr('class', 'country').attr('d', pathGenerator);});
Rendering the projected sphere outline
然后就是通過設置CSS文件設置顏色,為了讓地圖的圓形凸顯出來,我們要先給邊框創建一個path
svg.append('path').attr('class', 'sphere').attr('d', pathGenerator({type:"Sphere"}));
然后在CSS文件中根據設置的類設置顏色:
.country{fill: #15ed76;stroke: black;stroke-opacity: 0.3;
}.sphere{fill: #15beed;
}
Tweaking map styles
最后的圖形效果如圖:
代碼地址:https://vizhub.com/Edward-Elric233/b21d1d4d6db34c9092c3252f39212bda
Highlighting on Hover using CSS
上面的效果已經不錯了,但是如果我們想要鼠標放在上面就自動變色的話,我們可以在CSS文件里面添加hover
屬性,然后就可以了。
styles.css
.country:hover {
/* 鼠標放在上面可以變色 */fill : red;
}
效果圖:
Adding simple tooltips(using )
我們還希望鼠標停留在上面的畫可以提示國家的名稱,想要做到這點,我們可以給每個path
添加title
,然后設置文本為國家名稱即可。例如:
index.js
g.selectAll('path').data(countries.features).enter().append('path').attr('class', 'country').attr('d', pathGenerator).append('title')//添加title,然后鼠標放在上面就可以出現標題.text(d => d.properties.name);
我這里的數據直接就有國家名稱,視頻中的沒有還需要使用tsv
文件查找。如果有需要的話可以看原視頻。
Loading multiple data files
Looking up country name from id
Panning & Zooming
當然我們還希望能夠放大和縮小,這樣才能看到更多的細節。為了實現這個效果,我們要把所有的東西都放到g
上,然后再讓svg.call(zoom().on('zoom', callback))
添加鼠標滑輪事件。具體到這里我們希望圖像的大小可以跟隨滑輪的滾動而變化:
const g = svg.append('g');svg.call(zoom().on('zoom',() => {g.attr('
效果圖:
這里的地圖應該比上面的清晰許多,是因為這里使用的數據是以10m為單位的,所以分辨率高一點。如果需要的話只需要把最前面地圖的
topojson
的網址換成10m的即可:https://cdn.jsdelivr.net/npm/world-atlas@2.0.2/countries-10m.json
(比較大,加載稍微有點慢)
視頻中的內容到這里就結束了,可是我總覺得這樣的顏色有些丑,我想起來在以前做柱狀圖的時候我嫌棄他的顏色太丑自己做了一個選擇顏色的函數,在這里也可以用一下:
let colorSet = ['#eb2617', '#ffaa00', '#4dff00', '#00fbff', '#bb00ff', '#eeff00'];const createGetColor = (idx)=>{var i = idx || -1;return {get : () => {i=(i+1)%colorSet.length; return colorSet[i];}};
};const getColor = createGetColor();
createGetColor
函數會返回一個對象,對象中get
屬性為函數,這個函數中使用了外層的變量i
,因此i
不會被釋放掉,相當于靜態變量,每次調用這個函數這個變量都會加一,起到遍歷顏色數組的功能。
在有了這個獲取顏色函數以后我們只需要刪掉CSS文件中設置地圖顏色語句,然后在append
后面設置屬性即可。
g.selectAll('path').data(countries.features).enter().append('path').attr('class', 'country').attr('fill', getColor.get).attr('d', pathGenerator).append('title')//添加title,然后鼠標放在上面就可以出現標題.text(d => d.properties.name);
效果圖:
顏色選擇的有點鮮艷,不過看起來還不錯,有點世界地圖的感覺。
代碼地址:https://vizhub.com/Edward-Elric233/2e91c94015e345afb0c9f3ae6cde412f
感覺這個球體部分地方有些變形,我們可以換一個地圖的形狀
例如換成geoMercator
: