羅孚想要製做一份疫情場所分佈地圖,最初是由於看到我所在的城市(上海)疫情場所位置不許,想本身作一份數據並顯示在地圖上,結果一拖再拖而後疫情都快結束了[尷尬],不過我仍是花了一天時間研究了一下,因而有了這篇《如何製做一份疫情場所分佈地圖?》,要不就當羅孚手把手教你製做一份疫情場所分佈地圖吧[捂臉]。
本文是以上海地圖數據爲基礎、基於高德地圖API設計製做的一份城市地圖,若是你收集了你所在城市的地圖數據,那麼按照本文文末提供的源碼和數據結構,你也能夠直接複製出一份城市疫情場所地圖。要是你真實現了,記得要回來show給我看一下哦。javascript
上圖是幾個主要功能的預覽
不過只給個圖不給體驗,這不是羅孚的風格,直接上體驗網址:https://rovertang.com/map/shncov/
疫情場所分佈地圖現有的功能:php
其餘:縮放控件顯示、地圖範圍限定等
因爲是第一版,僅僅研究探討,因此更強大的功能還沒法實現,不過我會在下文中展望一下更強大的功能。html
兩個文件就實現了所有功能,還要作個概要設計?很差意思,請讓羅孚裝一下[捂臉]。實際上,羅孚在這事情上確實走了彎路。java
羅孚最開始考慮的實現方案,超級簡單,簡單到甚至不須要寫代碼和製做數據文件。
不論是高德、百度仍是騰訊,都提供了地圖數據管理方案,高德的雲圖、百度地圖的LBS雲、騰訊地圖的地點雲,直接使用他們的雲存儲,而後在地圖上添加一個自定義雲圖層或者經過數據檢索API取出數據後marker到地圖就好了。
雲數據方案是好的,但羅孚使用下來,居然都很差用,要麼沒法在地圖上顯示,要麼API接口不返回數據,只能說羅孚做爲一個非專業開發人員,確實太菜了一些。固然,也要批評一下高德,地圖若是是3D模式時,沒法使用雲地圖圖層,這一信息是在某一文檔的一行小字中找到的,擦,這坑挖的夠深。
自建數據庫成了惟一的選擇。
不過,爲了讓方案簡單易複製,使用MySQL彷佛重了一點,要不使用sqlite吧。但一想到要寫數據庫的增刪改查,又增長了很多麻煩,爲了快速實現,直接將最終數據作成了json文本,數據庫的操做,之後再考慮吧。
大言不慚的說,最後的實現框架是:json+js。嗯,兩個文件,一個json數據文件,一個js文件(寫在html文件裏了)。[憨笑]sql
扒別人的位置數據
羅孚的初衷是想本身收集和標註,自力更生是我國人民的傳統美德,但本人懶癌嚴重,因此最後也是取了個巧,扒了份別人的數據(僅使用了上海部分啊,其餘城市的沒要)。
固然,如何扒其餘平臺的數據,彷佛又能夠寫一篇文章,考慮同本教程有較大出入,加上這見不得人的伎倆,之後再說吧。數據庫
肯定好框架,定義好數據,能夠開始開發了,但因爲和地圖相關,在此多討論一下地圖平臺的問題。
通常來講,使用商業公司成熟的地圖API是最佳選擇:
高德和百度地圖的API:推薦。畢竟是國內不分伯仲的頂尖API。
騰訊地圖API:可用。可能能夠算國內老三,但用的人真少,看在微信、小程序都是鵝廠的產品,也是值得考慮的,看了下API,也基本能用。
mapbox API:可用,有難度。mapbox是開源地圖解決方案公司,屬於國際頂尖(在地圖上甚至比Google還強大哦),如今正在大力發展國內市場,這次製做的疫情地圖也超級漂亮(欣賞一下)。
Google maps API:不能用。雖然國際頂尖(地圖API鼻祖),但不能用的道理,你懂得。(有興趣的能夠了解一下我十年前拆解的Google Maps API v3離線開發包)
除了商業公司的方案,固然也可使用開源方案,好比leaflet。我看到天地圖上海作的地方疫情地圖就是用了leaflet。開源方案主要是功能框架,但地圖底圖數據,要麼用商業公司的,要麼就仍是本身扒了(羅孚也扒過:Google Maps瓦片(tile)地圖文件下載(1-11層級),今年過年太無聊,又扒了更多更細的數據[捂臉])。
地圖平臺的探討,真能夠再寫幾篇文章,對於本文的地圖平臺,最終選擇了高德,主要緣由是站在別人肩膀上的選擇。百度地圖API雖然我想用,但考慮到百度地圖座標是在GCJ02座標系下又作了一次加密,想到後續的數據座標混亂,仍是罷了罷了。json
繼續大言不慚的說說功能實現的詳細設計吧,咱們針對每一項功能作詳細的介紹以及實現上的注意事項,順便把我參考的地圖示例貼出來供你們參考。小程序
而地圖的風格,normal的色調太亮,換一個官方的遠山黛whitesmoke主題吧。
參考示例:
地圖建立:https://lbs.amap.com/api/javascript-api/example/map-lifecycle/map-show
設置地圖中心點/級別:https://lbs.amap.com/api/javascript-api/example/map/change-map-center
標準樣式主題:https://lbs.amap.com/api/javascript-api/example/personalized-map/set-theme-style
地圖類:https://lbs.amap.com/api/javascript-api/reference/mapapi
這一步算是本地圖DEMO的最核心功能了,雖然說比較簡單,就是遍歷json,而後批量添加marker到地圖就能夠了,但這裏遇到了一個坑,在marker上綁定click事件後,居然click任何一個marker,都是響應最後一個marker的氣泡框。
調整半天、搜索半天都沒能解決,羅孚差點想把整個DEMO都放棄,最後仍是搜索到了一個小小的提示,才解決了這個問題。感慨百度搜索真心不靈。
這個問題的解決方法:使用marker的extData。
參考示例:
覆蓋物的添加與移除:https://lbs.amap.com/api/javascript-api/example/map-componets/map-overlays
點標記:https://lbs.amap.com/api/javascript-api/example/marker/marker-content
自定義圖標:https://lbs.amap.com/api/javascript-api/example/marker/custom-icon
獲取某個覆蓋物(關於extData的使用):https://lbs.amap.com/api/javascript-api/example/common/ext-data/
默認樣式信息窗體:https://lbs.amap.com/api/javascript-api/example/infowindow/default-style-infowindow
Marker類:https://lbs.amap.com/api/javascript-api/reference/overlay#marker
InfoWindow 類:https://lbs.amap.com/api/javascript-api/reference/infowindow#InfoWindow瀏覽器
此功能是顯示本身的位置,若是定位成功,則基於自身位置顯示半徑爲1千米和3千米的圈,以瞭解附近範圍內大概有多少疫情場所marker。
須要注意,本處使用的是AMap.Geolocation,是高德地圖API的定位插件。
定位的一些細節邏輯:當定位成功後,原則上是須要將地圖的中心點移動到定位位置的。但若是定位信息中的citycode不是021,那麼就不要移動地圖中心點。對於沒法定位和定位成功返回的citycode不是021,那麼仍然是以上海市人民廣場爲地圖中心點。
參考示例:
瀏覽器精肯定位:https://lbs.amap.com/api/javascript-api/example/location/browser-location
圓的繪製和編輯:https://lbs.amap.com/api/javascript-api/example/overlayers/circle-draw-and-edit
AMap.Geolocation插件:https://lbs.amap.com/api/javascript-api/reference/location#m_AMap.Geolocation
能夠查看自身位置信息瞭解自身周邊的疫情狀況,那麼想看看某一小區或商場附近的疫情狀況是否能夠實現呢?這就須要用到查詢功能了。
這裏咱們使用高德的AMap.Autocomplete,是輸入提示插件,雖然不是地點搜索,但已經足夠用了,能出如今提示中的結果都是搜索頻率較高的結果,同時這個插件的使用也超級簡單,輸入綁定到某一輸入框,好比id爲search的input,結果綁定到某一div,好比id爲result的div,功能就實現了,你只要輸入內容,result中就出現結果了(簡單到讓羅孚瞠目結舌)。
完成上述操做,結果內容是沒法選擇的,好在插件提供了返回結果功能,在AMap中設置一個監聽事件,選擇某一結果後就能夠獲得該結果的詳細信息,我主要是取經緯度信息,而後在地圖上顯示一個marker就行了。
參考示例:
輸入提示:https://lbs.amap.com/api/javascript-api/example/input/input-prompt
添加簡易控件,就是在地圖右下角的放大和縮小按鈕,使用AMap.ToolBar便可,是地圖操做工具條插件。
爲了讓地圖範圍在某一範圍中顯示,能夠給地圖設置一個bound,使用map.setLimitBounds方法便可。
參考示例:
地圖控件:https://lbs.amap.com/api/javascript-api/example/map-componets/map-with-function-control
限制地圖顯示範圍:https://lbs.amap.com/api/javascript-api/example/map/limit-map-show-range
地圖操做工具條插件:https://lbs.amap.com/api/javascript-api/reference/map-control#AMap.ToolBar
本demo中使用的數據,總量100+,不算不少,但若數據量達到1000+,那麼加載的時間順序就顯得尤其重要,因此咱們在地圖加載完成(使用map.on 'complete')後,再去加載json數據。
這樣作的優點:先讓地圖顯示,而後看到地圖上出現marker,避免地圖長時間等待加載,畢竟用戶的耐心是有限的。
關於事件,因爲主要是針對地圖或覆蓋物類,因此使用這些類的on成員方法實現對事件的綁定。好比上面加載json數據是綁定在map的complete事件上的,好比氣泡框的顯示是綁定在marker的click事件上的。
對於非地圖或覆蓋物類的事件,那就只能增長addListener事件了,好比對輸入提示結果的操做。
參考示例:
地圖加載完成:https://lbs.amap.com/api/javascript-api/example/map-lifecycle/map-complete
事件:https://lbs.amap.com/api/javascript-api/reference/event
輸入提示後查詢:https://lbs.amap.com/api/javascript-api/example/poi-search/search-after-enter-prompt/
引入其餘地圖API
使用高德地圖API,雖然實現了此DEMO,但畢竟有自身的侷限性,綁定在了此平臺上,能夠考慮使用同一份數據製做基於百度地圖API、騰訊地圖API以及leaflet庫的地圖。
還有不少不少,沒法一一敘述,後續能夠考慮寫一篇疫情地圖功能對比的文章,看看別人在產品製做上的優劣。
專業的人作專業的事
羅孚本人不是程序猿,也應該有10年以上沒有碰過代碼了,此次作個DEMO都費了老半天的勁,只能感慨專業的事仍是由專業的人來作吧。
不過上面產品思考的功能開發,若是在屏幕前的你,有興趣幫助完成,那也歡迎聯繫我。不論是互相學習交流,仍是互相幫助提高,羅孚都願意,畢竟羅孚也是熱心腸嘛[憨笑]。
本文太囉嗦,一篇技術文章寫成了記敘文,羅孚自身也在感慨,看來之後能夠考慮作成PPT或視頻的形式,要麼更簡單明瞭,要麼更詳細清晰。
本文標題和開篇均提到了源碼和數據,若是是懂技術的你,應該是不屑的,或者Ctrl+U一下就拿到了(加密版本)。若是確實須要下載,能夠在「羅孚傳說」公衆號上回復「疫情場所地圖」便可(未加密版本)。若是須要帶詳細註釋的文件來研究,請加入羅孚的知識星球來取(帶註釋版本),固然還能夠附送超詳細瓦片地圖離線文件哦,後續也有更多內容分享。 好了,用地圖API製做一份疫情場所分佈地圖,今天,你會了嗎?歡迎聯繫羅孚,歡迎關注羅孚的公衆號(羅孚傳說)作更多交流,更歡迎加入羅孚的知識星球贊助羅孚得到更多有價值內容,咱們下一篇文章中見。