手把手教你快速構建一份全國疫情分布地圖


閱讀小提示:本文附送源碼,文末有鏈接,同時本文測試公眾號(羅孚傳說)的付費閱讀功能,1元看全文。

本文基於百度地圖API和fangkai提供的疫情數據API制作,是一份真實並實時的疫情場所分布地圖,演示地址:https://rovertang.com/map/ncov/

花絮

上次發表了如何制作一份疫情場所分布地圖?(附數據和源碼)一文的第二天,百度地圖開放平台就發表了一篇【教程】如何快速構建一張周邊疫情地圖,一度讓我同事以為是我投的稿。

羅孚確實沒投稿,可能是百度地圖不爽,你用高德地圖API做了份,那我也公開一份用百度地圖API的地圖吧,還附送了源碼和模擬數據

而高德地圖API,至今也沒有任何信息給到羅孚,反倒是騰訊地圖,同樣也是第二天,幾乎同百度差不多的時間,給羅孚發了郵件,沒搞懂百年不給羅孚發郵件的騰訊位置中心,怎么突然會有我的郵箱地址。

騰訊位置中心發來的郵件主題“騰訊位置服務抗擊疫情保障計划:免費配額提升至3倍!”,一聽就是一個非常有吸引力的標題,點進去一看,還提供了“緊急上線疫情小區地圖,開放給所有開發者接入”,不僅營銷做的好,還實用啊,趕緊申請。

本以為騰訊地圖開放平台提供了數據API,結果實際僅僅是一個H5的頁面(沒搞懂這個鏈接給我開放了啥),再發郵件咨詢數據API的事宜,就沒人回復了,一度讓羅孚想去扒騰訊的API數據。

羅孚“將百度地圖API和騰訊數據雜交成一份真實的疫情場所地圖”的想法泡湯了,於是去GitHub搜索了一圈,雖然大部分都是扒丁香園的疫情數量數據,但也找到了一份疫情小區分布地圖,是安徽大學的一名學生制作的,還開放了API(點贊點贊),最終羅孚用此數據API同百度地圖API雜交成功。

效果預覽

詳情信息、城市點位、地圖查詢

功能說明

顯示疫情小區

當地圖層級大於9時,顯示疫情小區位置,疫情小區位置數據由數據API根據城市名獲得,城市名為地圖中心點所在的城市名,當移動地圖后地圖中心所對應的城市名發生變化,則加載新城市名對應的疫情小區位置數據。

顯示疫情小區詳情

點擊疫情小區位置marker,從底部彈出疫情位置的詳細信息,詳細信息內容來自數據API,包括位置名稱、省、市、縣以及數據來源和來源鏈接。

顯示省市位置

當地圖層級在6到10之間,則顯示城市點位數據,當地圖層級小於7時,顯示省份點位數據,此數據羅孚整理,增加了省、市名稱。

自定位和地圖查詢

自定位功能用於顯示自身位置信息,需要允許定位才能顯示,如果定位失敗則顯示北京市地圖和數據。

地圖查詢功能,輸入關鍵詞后,自動顯示最佳結果,點擊某一結果可以將地圖定位到該結果並顯示周邊疫情信息。

技術點

由於源碼不是羅孚所寫,原文也提供了概要的源碼說明,所以羅孚在此僅介紹一下羅孚修改的幾個關鍵點,以及這里的坑,順便再吐槽一下百度地圖提供的源碼。

根據不同比例尺顯示不同數據

顯示省份、城市和小區

數據加載有兩個問題,數據量和美觀度。

一次性加載全國數據,對於近萬的數據量,地圖API提供方表示無壓力,但對開發人員來說,加載速度是有影響的,所以我們只加載一個城市的數據,以加快數據加載速度。
地圖數據API本身的速度

如果只加載一個城市的數據,那么在全國地圖或世界地圖時顯示,你會發現所有數據縮在了一坨,這樣的美觀度我們是無法接受的。所以我們要分層級(不同比例尺)的來顯示地圖。
全國地圖下顯示一個城市的效果

源碼中本身設計了不同比例尺下顯示不同數據的邏輯:

不同比例尺不同數據JS

羅孚修改了省份和城市數據,帶名稱,同時將詳細數據改成API獲取方式。

更新數據的邏輯放在了地圖縮放過程中:

縮放完成后更新地圖數據JS

羅孚不得不吐槽,地圖縮放跨一層級就重新加載一次地圖數據,既影響了速度,又增加了加載次數,被調用的API要哭,原本在詳圖層級只需加載一次的數據,最后要被多次加載,每次加載就會產生一次訪問,就會增加服務器的訪問量,浪費人家服務器的資源。

所以,羅孚修改為當進入詳圖時,加載該城市的疫情小區數據,只要不縮小到城市或省份地圖,那么該城市的數據就不會重復加載,降低了API的訪問量。

城市發生變化后重新加載數據

拖動地圖,城市發生變化,自動加載新城市數據

當用戶拖動或縮放地圖時,如果地圖中心的城市發生了變化,那就加載該城市的數據,這樣的體驗應該是最棒的。

羅孚本想在點擊城市marker時根據城市名加載該城市數據,但此方法無法解決移動地圖過程中的城市變化加載不同城市數據問題。瀏覽代碼時,發現在移動和縮放地圖事件中就存在城市名的判斷:

根據地圖中心位置獲取城市名js

羅孚吐槽一下Geocoder類,此類可能是異步加載(羅孚不確認),所以城市名的獲取要慢於后續執行的代碼,導致后面使用該類的城市名為空,表現為選擇從城市地圖縮放進入到詳情地圖時,地圖第一次無法加載城市數據。於是我在城市marker的click事件中,在centerAndZoom方法前先將currentCity變量變更為城市marker的name,解決了點擊城市marker后不加載該城市數據的問題。

另外,如果每移動一次地圖就加載一次該城市的數據,那數據API的訪問量也將無法想象,所以羅孚定義了一個beforeCity,當獲得了currentCity后,同beforeCity比較,如果城市名發生了變化,那就加載新城市名的數據,加載完成后更新beforeCity為currentCity,這樣就做到了城市名不變就不重新加載數據。同時,增加了zoom > 9的判斷,在城市圖和省份圖下移動地圖,無需加載城市詳圖數據。

顯示詳情和隱藏詳情

點擊小區marker顯示詳情,拖動地圖隱藏詳情

源碼中定義了顯示詳情卡片showinfoCard和隱藏詳情卡片hideInforCard函數,但詳情卡片中的內容沒有傳遞,所以羅孚稍加改造,在讀取城市詳圖數據時,將詳情內容組織好后傳給showinfoCard函數。

另外,發現隱藏詳情卡片的時機有問題,沒有及時調用hideInforCard函數,於是在移動結束后就隱藏詳情卡片。當然,你也可以添加在地圖點擊事件中。

顯示詳情卡片內容和隱藏詳情卡片的時機js

羅孚再吐槽一下,地圖API本身配合marker點擊就有信息窗口InfoWindow類,並且顯示和隱藏都設計了時機或方法,那為什么還要自定義一個從底部彈出來的詳情卡片?吃力不討好還費勁。

定位、搜索及周邊疫情信息

定位模塊和搜索功能是現成的,羅孚未做任何修改,所以不在此贅述,但需要吐槽一下,源碼中的定位模塊感覺是自己封裝的(羅孚不確認),而高德地圖API是直接封裝成了一個公共的類,相比之下似乎有點不專業。

顯示疫情最近的距離數據以及1公里內或3公里內的疫情總數量,屬於周邊疫情信息模塊,羅孚未去實現,簡單說一下思路,兩個方案吧。如果你本身有數據,可以做一個根據該位置搜索周邊數據的API,可以直接提供結果,但可能需要服務端支撐。如果不想自己寫服務端,那就根據數據API獲取的數據,遍歷該城市的數據,做距離排序並聚合數量,一樣可以達到疫情信息展示的功能。有興趣的可以嘗試一下。

小結和福利

百度地圖雖然提供了源碼,但源碼的質量實在是soso,邏輯思考不足,甚至語法都存在不規范(比如缺少代碼結尾符號)。同時,對於JS API的GL版和V3.0版,雖然存在繼承,但在文檔中未能很好體現,導致看起來GL版功能很少。另外,對於百度地圖API的類,感覺封裝的數量少了點,而在可定制性上又欠缺了一些,這僅僅是羅孚的感覺吧,畢竟未通讀百度地圖API和示例。

最后的福利依然是源碼放送啦,只是羅孚想測試一下公眾號新的付費閱讀功能,所以本文需要付費1元查看全文,包括下面的下載鏈接哦。下載文件簡要說明如下:

疫情地圖源碼說明

對了,還會多送一份地圖,一個html文件就可以搞定的地圖,自己拿到后再修改布局元素相關的內容吧,數據和地圖的代碼都可以不用動哦,羅孚僅保存了html,未做任何修改哦,具體效果如下:

一個html文件的疫情地圖

下載地址:在“羅孚傳說”公眾號后台回復"疫情場所地圖"地圖試試。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM