標籤:

如何用Mapbox製作一張音樂地圖?這張地圖告訴你全世界都在聽什麼

如何用Mapbox製作一張音樂地圖?這張地圖告訴你全世界都在聽什麼

沒有時間更沒有耐心閱讀長文?你不是一個人。所以如果把冗長的文字內容變得更視覺友好會怎樣?

The Pudding——這個用視覺化方式講故事的網站,在一群熱愛音樂、電影和編輯的工程師們收下誕生了。創始人之一 Matt Daniels 跟他的工程師小夥伴們假不正經地管自己叫「記者工程師」(Journalist-Engineer)。

The Pudding 經常搞出一些讓你大呼「WOW」的酷項目!比如去年11月,他們就做了一張音樂地圖,告訴你世界各地的人們都在 Youtube 上聽什麼音樂。

去年11月,全世界都在聽Perfect

Perfect by Ed Sheeran?

v.qq.com

Ed Sheeran那麼問題來了,這張音樂地圖,究竟是怎麼做出來的?Matt 跟我們分享了他基於 Mapbox 地圖來進行項目開發的經驗。

?? 初步構想——工具和數據

在考慮了許多地圖工具以後,Mapbox 的 JS 庫是最為完整的,可以實現各種炫酷的地圖效果。同時,Mapbox Studio 的圖形界面非常友好,適合整合音樂數據。

那麼,這張地圖的數據從哪裡獲得呢?為了確定在當地哪首歌最受歡迎,Matt 選擇抓取 YouTube 上的播放數據。由於 Youtube 的數據是完全公開,並且在上面聽音樂不需額外付費,這樣產生的數據要比 Spotify 等付費平台上要更加清晰。

當我們有了不同地區的播放量與該地區的經緯度數據,就完成了構建音樂地圖的所需基本要素。以下是一個數據示例,展示了葉門城市薩那播放量排第一的音樂來自歌手 Nicos:

"artist_name","latitude","longitude","views","track_link","track_name","rank","country_code","geo_name","geonameid""Nicos",15.35472,44.20667,108707,"ykPmM7Me2fM","Secret Love",0,"YE","Sanaa",71137

使用 Mapbox Studio,我們可以方便地整合獲得的數據,並在地圖上生成不同大小的圓圈來代表音樂的流行程度。Mapbox 的標籤碰撞檢測功能可以避免過度渲染,在合適的位置添加標籤,讓地圖更加美觀。

完成這一步之後,我們便可以看到大致的區域音樂流行趨勢了。但視覺上我們可以做優化,考慮合併一下相鄰地區的圓圈,讓它們成為一個整體,例如上圖中從墨西哥到智利之間合併成一個紫色區域。

?? 使用 Maobox 創建密度分布圖

通過 Mapbox Studio 可以直接生成密度分布圖,不過 Matt 選擇使用 web API (mapbox-gl-js) 來以代碼的方式構建。這是國家為單位的密度分布圖的效果:

我們正是想採用這樣的方式來展示簡化版音樂偏好地區分布圖。首先使用 map.addLayer 將國家的邊界添加到地圖中,然後使用樣式規範來填充顏色,直到數據中的 stops。以下代碼簡單來說,就是執行「如果是國家X,那麼填充Y顏色」。

在代碼實例中,CountryStopsFill 是儲存所有國家和對應顏色的數組,其中每一首歌曲所代表的顏色保持相同。(如 [US, blue])

map.addLayer({ "id": "admin-0-fill", "type": "fill", "source": "admin-0", "maxzoom": maxZoomAmount, "source-layer": "boundaries_admin_0", "paint": { "fill-outline-color":"rgba(0,0,0,0)", "fill-opacity":fillOpacity, "fill-color": { "default":"rgba(0,0,0,0)", "property": "id", "type": "categorical", "stops": countryStopsFill } } }, city-dots-2);

但是更加有趣的部分來自再進一步細化到地區的層面,我們需要在地圖上繪製更多的多邊形瓦片來代表當地最流行的歌曲。

? 將元數據繪製到密度分布圖

Mapbox 早已為你準備好了世界行政區域圖的相關數據,亞洲國家的行政劃分非常細,但這張地圖的數據非常全面,方便你在數倍縮放級別進行單個地圖瓦片渲染。

這一數據目前暫時只提供給 Mapbox 的商業客戶,Matt 的聯繫到了 Mapbox 團隊的成員,獲得了數據的調用許可權,這樣我們便可以進行下一步的繪製。

??位置查詢

將獲得的音樂數據對應到國家這一層面很容易,但再對應到更小的層面(如一個縣)則有些困難。如何對這些更小量級的城市數據進行查詢,並且與瓦片形狀相對應呢?這時候 Mapbox 的多邊形數據查詢功能就可以幫到你了。

這個查詢的基本邏輯如下:將某個數據點遍歷查詢資料庫,從9個縮放級別的層面找到相應的城市多邊形範圍,以及郵編和行政所屬等。

https://api.mapbox.com/v4/mapbox.enterprise-boundaries-a0-v1,mapbox.enterprise-boundaries-a1-v1,mapbox.enterprise-boundaries-a2-v1,mapbox.enterprise-boundaries-a3-v1,mapbox.enterprise-boundaries-a4-v1,mapbox.enterprise-boundaries-a5-v1,mapbox.enterprise-boundaries-p1-v1,mapbox.enterprise-boundaries-p2-v1,mapbox.enterprise-boundaries-p3-v1,mapbox.enterprise-boundaries-p4-v1/tilequery/"+longitude+","+latitude+".json?access_token=TOKEN

你可以在 Google Street 中看到以上查詢的數據。每個城市都有一個相應的多邊形ID。

比如紐約市的多邊形 ID 為 USA136,代表其上屬於紐約州,國家 ID 為 USA236061。

?? 繪製密度分布圖

最終我們決定使用 boundaries_postal_1(以郵編作為區分,相對大範圍的多邊形),boundaries_admin_1(州)以及 boundaries_admin_0(國家)。

代碼十分簡單:

map.addSource("admin-1", { type: "vector", url: "mapbox://mapbox.enterprise-boundaries-a1-v1" });

之後是:

map.addLayer({ "id": "admin-1-fill", "type": "fill", "filter":filterValue, "maxzoom": maxZoomAmount, "source": "admin-1", "source-layer": "boundaries_admin_1", "paint": { "fill-outline-color":"rgba(0,0,0,0)", "fill-opacity":fillOpacity, "fill-color": { "default":"rgba(0,0,0,0)", "property": "id", "type": "categorical", "stops": stopsAdminOneFill } } }, city-dots-2);

同之前介紹的一樣,fill-color 是一個大的數組,包含了州的ID與對應的每首歌的顏色,繪製過程在 JS 文件中完成。

首先要做的是將數據集(每個城市與目前最流行的歌曲,同時還有其對應的多邊形ID)同每個瓦片數據(如 boundaries_admin_1)整合到一起。

var topByAdminOne = d3.nest().key(function(d){ return d.boundaries_admin_1; }) .rollup(function(leaves){ return d3.nest().key(function(d){ return d.track_name }) .rollup(function(leaves_sub){ return d3.sum(leaves_sub,function(d){return +d.views;}); }) .entries(leaves).sort(function(a,b){return +b.value - +a.value;}).slice(0,1)[0].key; }) .entries(city_data)

有了這樣的數據集,我們對其分配一種顏色:

var stopsAdminOneLine = topByAdminOne.map(function(d){ var color; if (topSongs.slice(0,colorSliceAmount).indexOf(d.value) > -1){ color = colorsManual[topSongs.slice(0,colorSliceAmount).indexOf(d.value)]["label"]; } else{ color = otherScale(topSongs.indexOf(d.value)); } return [d.key,color] });

這樣確保同一歌曲在不同區域上呈現的顏色相同。

?? 點擊標籤播放 Youtube 視頻

接下來我們在歌曲標籤上建立一個點擊事件,播放對應的 Youtube 視頻。因為有了 Mapbox 的標籤碰撞檢測功能,我們可以避免一次性出現大量的標籤,當且僅當我們點擊可見標籤時播放的事件才會被觸發。

我們已經有了對標籤的跟蹤數據,將其上傳到 Mapbox Studio 並根據其城市的地理位置渲染到地圖的相應位置。

map.on(click, function(e) { var features = map.queryRenderedFeatures(e.point,{ layers: [medium-city-label-2,country-label,major-city-label-2,minor-city-label-2] }); if(features.length > 0 && markerTimeout == false){ var trackData = features[0].properties; } });

以上代碼邏輯是:「如果地圖上發生了一次點擊,將檢查它是否在X, Y或者Z層的渲染標籤上,如果在的話,獲取相關數據。」並用其觸發 Youtube 視頻的播放。

懸停事件也是如此:

map.on(mousemove, function(e) {var featureCountry = map.queryRenderedFeatures(e.point,{ layers: [admin-0-fill] });});

在 mousemove 中,我們查找其是否在某一特定渲染層上,即 admin-0-fill 這個數據,代表國家的多邊形,並將查找到的國家名稱等顯示出來。

?? 大功告成!

到此,這張音樂地圖就基本製作出來啦!當然,Matt 還添加了一些小細節,不知道你在使用過程中有沒有發現更多有意思的東西呢?從這一項目中,我們或許可以得到一些構思自己地圖的靈感,現在就上手製作你的主題地圖吧!

?? 我們歡迎你與我們分享你的作品,你可以在微博上 @Mapbox,或者tag #mapbox# ,或者直接在微信上發給我們??

推薦閱讀:

怎麼評價徐佳瑩?
尤克里里常見按弦問題之按弦時如何進行手指分配?
蔡依林(Jolin Tsai)的那首歌曲,你最喜歡?
周杰倫的胸肌,我竟然有點想靠!
放克貝斯:只需一個音,也可以玩得律動十足!

TAG:音樂 | 可視化 |