如何製做一份疫情場所分佈地圖?(附數據和源碼)

羅孚想要製做一份疫情場所分佈地圖,最初是由於看到我所在的城市(上海)疫情場所位置不許,想本身作一份數據並顯示在地圖上,結果一拖再拖而後疫情都快結束了[尷尬],不過我仍是花了一天時間研究了一下,因而有了這篇《如何製做一份疫情場所分佈地圖?》,要不就當羅孚手把手教你製做一份疫情場所分佈地圖吧[捂臉]。
本文是以上海地圖數據爲基礎、基於高德地圖API設計製做的一份城市地圖,若是你收集了你所在城市的地圖數據,那麼按照本文文末提供的源碼和數據結構,你也能夠直接複製出一份城市疫情場所地圖。要是你真實現了,記得要回來show給我看一下哦。javascript

功能和效果預覽

疫情場所地圖效果預覽
上圖是幾個主要功能的預覽
不過只給個圖不給體驗,這不是羅孚的風格,直接上體驗網址:https://rovertang.com/map/shncov/
疫情場所分佈地圖現有的功能:php

  1. 地圖顯示
  2. 疫情場所顯示
  3. 我的位置顯示
  4. 地圖搜索
  5. 其餘:縮放控件顯示、地圖範圍限定等
    因爲是第一版,僅僅研究探討,因此更強大的功能還沒法實現,不過我會在下文中展望一下更強大的功能。html

    概要設計

    兩個文件就實現了所有功能,還要作個概要設計?很差意思,請讓羅孚裝一下[捂臉]。實際上,羅孚在這事情上確實走了彎路。java

    實現框架

    羅孚最開始考慮的實現方案,超級簡單,簡單到甚至不須要寫代碼和製做數據文件。
    不論是高德、百度仍是騰訊,都提供了地圖數據管理方案,高德的雲圖、百度地圖的LBS雲、騰訊地圖的地點雲,直接使用他們的雲存儲,而後在地圖上添加一個自定義雲圖層或者經過數據檢索API取出數據後marker到地圖就好了。
    雲數據方案是好的,但羅孚使用下來,居然都很差用,要麼沒法在地圖上顯示,要麼API接口不返回數據,只能說羅孚做爲一個非專業開發人員,確實太菜了一些。固然,也要批評一下高德,地圖若是是3D模式時,沒法使用雲地圖圖層,這一信息是在某一文檔的一行小字中找到的,擦,這坑挖的夠深。
    自建數據庫成了惟一的選擇。
    不過,爲了讓方案簡單易複製,使用MySQL彷佛重了一點,要不使用sqlite吧。但一想到要寫數據庫的增刪改查,又增長了很多麻煩,爲了快速實現,直接將最終數據作成了json文本,數據庫的操做,之後再考慮吧。
    大言不慚的說,最後的實現框架是:json+js。嗯,兩個文件,一個json數據文件,一個js文件(寫在html文件裏了)。[憨笑]sql

    數據的定義和來源

    對於地圖數據,必須的字段可能有:
  • 名稱
  • 經度
  • 緯度
  • 地址(可選)
    對於疫情,可能的字段有:
  • 次數 (有些省市會提供這個地址發生的次數)
  • 類型 (能夠細分爲小區、商場等)
  • 時間 (發現時間)
  • 來源 (數據源來自哪裏)
    呃,考慮的是否是有點複雜?羅孚實際上也沒有用這麼多數據內容,數據字段越多,內容越豐富,實現難度也就越大,做爲一個DEMO,就只考慮必須的名稱(實際是用地址代替的)和經緯度吧。
    定義完字段,就要製做數據了,這些點位數據怎麼來呢?逃不出兩種方式:
  1. 本身收集和標註
  2. 扒別人的位置數據
    羅孚的初衷是想本身收集和標註,自力更生是我國人民的傳統美德,但本人懶癌嚴重,因此最後也是取了個巧,扒了份別人的數據(僅使用了上海部分啊,其餘城市的沒要)。
    固然,如何扒其餘平臺的數據,彷佛又能夠寫一篇文章,考慮同本教程有較大出入,加上這見不得人的伎倆,之後再說吧。數據庫

    地圖平臺的選擇

    肯定好框架,定義好數據,能夠開始開發了,但因爲和地圖相關,在此多討論一下地圖平臺的問題。
    通常來講,使用商業公司成熟的地圖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

    詳細設計(功能實現)

    繼續大言不慚的說說功能實現的詳細設計吧,咱們針對每一項功能作詳細的介紹以及實現上的注意事項,順便把我參考的地圖示例貼出來供你們參考。小程序

    地圖顯示

    地圖顯示是最基本的功能,有一些地方須要注意,談談我在地圖上的一些考慮。
  3. 考慮到是地方地圖,那麼全國地圖、世界地圖層級就不要顯示啦,因此我把地圖層級設置在了10-18之間。
  4. 既然是專題地圖,那麼雜項就不要顯示了,好比室內地圖、地圖上的熱點等,都設置爲false吧。
  5. 而地圖的風格,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

    添加疫情場所marker並彈出氣泡框

    點擊marker後彈出氣泡框
    這一步算是本地圖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千米範圍圈
    此功能是顯示本身的位置,若是定位成功,則基於自身位置顯示半徑爲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

    添加查詢功能

    經過輸入顯示結果提示,點擊後跳轉到該位置marker
    能夠查看自身位置信息瞭解自身周邊的疫情狀況,那麼想看看某一小區或商場附近的疫情狀況是否能夠實現呢?這就須要用到查詢功能了。
    這裏咱們使用高德的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/

    延伸思考

    產品思考

    本文真的僅僅是一個DEMO,還有甚多的功能未能實現:
  6. 數據管理後臺
    直接使用json文本做爲數據源,沒法增刪改查確實是一個缺憾,須要多數據作一個管理,能夠查詢地圖數據、添加數據、修改數據,這個功能下也包含了很多的小功能。
  7. 更多地圖顯示方式
    僅僅顯示marker,顯示方法太粗糙,marker按理是在詳圖層級(好比16級及以上)才顯示的內容,能夠考慮引入聚合圖和熱力圖。
    好比10到12層級,能夠考慮按照地區對疫情場所數據進行聚合顯示,按地區顯示每一區域總量總量的marker。
    好比13到15層級,能夠考慮顯示熱力圖,由於在此層級下查看疫情出現的熱度可能反而更直觀一些。
  8. 計算距離和提醒
    在當前位置或查詢結果數據上,顯示距離最近的疫情場所和距離信息,以讓自身瞭解危險的程度。
  9. 引入其餘地圖API
    使用高德地圖API,雖然實現了此DEMO,但畢竟有自身的侷限性,綁定在了此平臺上,能夠考慮使用同一份數據製做基於百度地圖API、騰訊地圖API以及leaflet庫的地圖。
    還有不少不少,沒法一一敘述,後續能夠考慮寫一篇疫情地圖功能對比的文章,看看別人在產品製做上的優劣。

    開發思考

    不是開發人員,但用代碼堆起了這個DEMO,那麼也說說在開發上的思考吧。
  10. 不要重複造輪子
    站在巨人肩膀上,用成熟的API,其實挺好的。
    有時候你的目標是實現功能,而不是創造一個有競爭力的平臺,那麼你就沒有必要思考本身開發一個平臺,甚至連選擇哪一個平臺都不須要太多的顧慮。
  11. 專業的人作專業的事
    羅孚本人不是程序猿,也應該有10年以上沒有碰過代碼了,此次作個DEMO都費了老半天的勁,只能感慨專業的事仍是由專業的人來作吧。
    不過上面產品思考的功能開發,若是在屏幕前的你,有興趣幫助完成,那也歡迎聯繫我。不論是互相學習交流,仍是互相幫助提高,羅孚都願意,畢竟羅孚也是熱心腸嘛[憨笑]。

    福利時間

    本文太囉嗦,一篇技術文章寫成了記敘文,羅孚自身也在感慨,看來之後能夠考慮作成PPT或視頻的形式,要麼更簡單明瞭,要麼更詳細清晰。
    本文標題和開篇均提到了源碼和數據,若是是懂技術的你,應該是不屑的,或者Ctrl+U一下就拿到了(加密版本)。若是確實須要下載,能夠在「羅孚傳說」公衆號上回復「疫情場所地圖」便可(未加密版本)。若是須要帶詳細註釋的文件來研究,請加入羅孚的知識星球來取(帶註釋版本),固然還能夠附送超詳細瓦片地圖離線文件哦,後續也有更多內容分享。 好了,用地圖API製做一份疫情場所分佈地圖,今天,你會了嗎?歡迎聯繫羅孚,歡迎關注羅孚的公衆號(羅孚傳說)作更多交流,更歡迎加入羅孚的知識星球贊助羅孚得到更多有價值內容,咱們下一篇文章中見。

相關文章
相關標籤/搜索