分享一下如何制作專業的手繪電子地圖,
一、智慧導覽系統介紹
手繪電子地圖,就是把手繪地圖覆寫到地圖上,游客或者普通用戶,可以在手機上通過地圖的鏈接(或者現在流行的小程式)打開使用,是一種使用非常方便,集“視、聽、路徑規劃、實時導航”等諸多功能于一體的智慧導覽系統,也是現在很多景區為游客提供的增加便捷性和游玩體驗的一項功能,
最重要的兩點,我認為是:
1.手繪圖本身
手繪圖的美觀度、清晰度、完整度、準確度,決定了圖的檔次格調的高低,也是手繪設計師的技術水平、設計能力、規劃能力、溝通能力等綜合性體現,
2.實時導航功能
如果說手繪圖本身是面子,讓人對地圖有第一印象和直觀感受,那么實時導航功能則是地圖的靈魂和里子,沒有實時定位和動態路徑規劃導航功能的地圖,只是一個可觀而不可用的花瓶,沒有使用價值,沒有準確的而高效的實時導航演算法,就不能把地圖價值在游客手里發揮到最大,
因為多年的從業經驗,我從一個純技術的角度來分享一下如何實作這樣的“智慧導覽系統”,
二、智慧導覽系統功能
先看一個參考示例圖(根據實際情況,只添加了必要的功能):
? 
參考示例圖
1.基礎功能
地圖功能的設計,包括需要哪些功能,需要怎么展示,地圖點位的圖示等細節,不一而足,每個需求方可能要的也不一樣,但總體來說,可能包含如下:
景點介紹:這是智慧導覽系統最基礎的功能之一,在系統后臺可以在地圖上添加景點標注,并完善相應的介紹資訊,包括圖片、文字、圖文、語音、視頻等內容,
服務設施:在地圖上添加區域內的服務設施,如廁所、游客中心、停車場等內容,
商家資訊:在地圖上添加區域內的商家,如酒店、餐飲、特產等商家,用戶可查看商家介紹、商家產品,并可支付下單購買,
景區公告:在后臺添加景區最新公告,如閉園通知、開園通知、最新活動等資訊,
線路推薦:在后臺設定推薦的線路及景點,游客在地圖上可點擊查看,并在地圖上直觀的規劃出推薦的路徑,模擬導覽游覽,非常直觀明了,
咨詢電話:可在后臺設定景區的咨詢、客服的聯系方式,如電話、微信、微博等,
景區720:可拍攝制作景區的720全景,并在地圖上標注展示,更直觀的向游客展示景點的實景,
2.增強功能
智慧導覽系統還應該具備如下增強功能,才能更好的增強客戶的服務能力、滿足用戶的使用需求,這也是當前電子手繪地圖系統的重點和難點,
實時定位:基于客戶端的位置獲取介面(如上文,可能大部分是微信環境里,或者瀏覽器環境),實時獲取用戶當前的位置資訊,當然,位置的精度可能會受到諸多方面因素的影響,如天氣、建筑物遮擋、設備本身的性能或GPS模塊的精度、網路狀況等,在理想的情況下,精度甚至可達到10到20米左右的偏差,這種精度,在民用已經算是極致了,為什么不給出更精確的精度,可能一方面是設備、技術等因素限制,另一方面,從安全角度來看,可能這也超出民用的范疇,當然,話說回來,從我們的實際使用場景來看,這樣的精度其實已經遠遠的滿足我們的需求了,這里說個題外話,為什么我們在手機上使用地圖APP導航的時候,不管是駕車還是步行,看上去都能做到精準無誤呢?(如駕車,在路口轉向時,基本上達到米級的精度)關于這一點,我是這樣思考的:地圖APP是基于設備的定位,然后再結合當前使用者的導航方式、路徑規劃、設備朝向、速度等多方面綜合的因素,用強大的后臺演算法為用戶的當前位置做了智能的“糾偏”,那為什么我們智慧導覽系統不做這樣的糾偏呢,從實際出發,這一方面是我們的資料量遠遠不夠豐富完善,另一方面是“性價比”不高,在園區內的導航,不需要這樣的“糾偏”已經可以滿足需求,而要做這樣的“錦上添花”的功能,則需要付出指數級甚至更高的成本和代價,
動態路線規劃:基于前端設備“實時定位”的能力,智慧導覽系統實時計算用戶當前位置和指定目的地的路徑,指定的目的地,可以是地圖上標注的任意一個點位,如景點、服務設施、商家等,這一點,和地圖APP的導航功能非常類似,園區內很多情況下,沒有地圖APP平臺采集路線,所以需要我們人工在智慧導覽系統后臺標注和實際情況一致的路線,或者通過智慧導覽系統提供的路線采集工具,安排人員現場采集,其實,地圖平臺的路線采集也是這樣做的,各大地圖平臺,都有國家發放的專業牌照,然后通過路線采集人員駕車或步行,采集、更新每個城市的道路(仔細想想,這是一個多大的作業量和成本,我們每個人都可以免費的使用這些服務,感謝他們的付出成本和辛苦),
自動觸發:基于“實時定位”和“動態路線規劃”能力,用戶達到系統設定的點位附近時,可以自動觸發后臺配置的各種功能,如自動播放景點的語音講解、展示圖文內容,或推送商家的優惠券等,為用戶提供便利、人性化的智慧服務,
多語言:多語言是智慧導覽系統滿足國際化需求的一個增強功能,系統具備基本的漢語、英語選擇,還具備很便捷的擴展其他語種的設計和功能,
3.地圖個性化
智慧導覽系統不應該是一個單純的功能性的系統,還應該有更多豐富的、多元化的功能,為用戶提供更多個性化、趣味化的服務,
個人中心:系統具備用戶個人中心的功能,用戶可以對地圖上的景點進行點贊、評論等操作,然后可在個人中心查看,
營銷、廣告:后臺可在地圖上添加固定的營銷、廣告等資訊,增強能力和滿足運營需求,
優惠券:后臺可設定地圖上的商家發送優惠券,吸引、導流游客進店,帶動消費,
尋寶游戲等活動:后臺可在地圖上添加尋寶指引點位,引導游客到指定地點掃碼積星對話獎品,
標注圖示動效:所有標注點的圖示,可設定一些動效,增加地圖的趣味性和個性化,
三、技術堆疊的選擇
從這里開始后面的內容,有一定的行業背景或經驗的人,能更好的理解,我盡量說得通俗易懂一些,如果你覺得一些專業名詞不明白是什么意思,可以直接跳過,
現在絕大部分業務系統的開發,都是基于一個成熟的技術堆疊來實作,這樣可以極大的節約基礎設施的成本,而且效率得到極大的提高,甚至某些系統或行業的應用及系統,不基于一些成熟的技術堆疊,想要完全自主開發,幾乎是不可實作的,
智慧導覽系統,建議基于這樣的一個技術堆疊:
1.服務器
使用成熟的云平臺,國內成熟好用的幾家,業內人都知道,
2.前端平臺
如今最大的前端平臺是微信小程式,還有就是瀏覽器直接通過鏈接打開,不過就智慧導覽系統來說,大部分情況下,微信小程式也是基于Webview控制元件來呼叫,本質上和瀏覽器的直接打開沒什么區別,就是HTML5+JavaScript+CSS3來實作,但是微信的生態內,會有一些微信開放的額外的一些介面和功能,比如說:可以使用微信提供的位置獲取介面,來為游客獲取更精準的定位,
3.地圖平臺
智慧導覽系統只能基于地圖的開放平臺來實作,目前國內幾家大而成熟的地圖平臺:高德地圖、百度地圖、騰訊地圖,建議首選高德地圖,次選百度地圖,為什么呢?
地圖有個“層級(Zoom)”的概念,就是用戶打開地圖,放大縮小,就是顯示的不同的層級,現在地圖平臺開放的層級,高德地圖最大為19級,百度地圖為18級,而同級別的情況下,高德地圖也更大一些,因此,建議選擇高德地圖,可以做更精細化的地圖,騰訊地圖多不做介紹,
另外,如果涉及國外的景區或地點,那谷歌地圖是不二的選擇,國內的地圖在國外沒有完整的內容,而且訪問速度也很隨緣,
四、開發介紹
具體開發內容,這里主要介紹涉及地圖核心的部分,其他比如資料庫設計、后臺管理系統等不做過多介紹,
1.開發語言選擇
后端開發:目前流行的開發語言如Java、PHP、Python等都是不錯的選擇,每個語言都有自己的特色,就個人而言,我比較喜歡Java和PHP,Java純面向物件,適合大型專案,運行速度較快;PHP靈活簡單,開發效率很高,現在利用有Swoole這樣的擴展,也可以做到運行速度很快,
前端開發:前端開發老生常談,JavaScript+HTML5+CSS3,千年不變的三板斧,但是可選擇的框架或者庫現在比較多,JavaScript有之前非常流行的JQuery庫,也有現在很火的Vue等框架,總之,做為開發者,你最擅長的可能就是最適合的選擇,當然,你也可以選擇學習新的知識和技術代替曾經最擅長的,
2.地圖基礎知識
這一點,是核心,基礎中的基礎,原理也比較復雜,因為地球是一個球體,是立體的,并不是天圓地方的一個平面,所以,首先,需要引入一個叫“坐標系統”的概念,
當前常見的坐標系主要有三種:
地球坐標系:WGS84,常見于GPS設備,Gooogle地圖(非中國區域)等國際標準的坐標體系 ,
火星坐標系:GCJ-02,中國國內使用的被強制加密后的坐標系,如高德地圖、騰訊地圖、谷歌地圖(中國區域)的坐標就屬于此類坐標系,
百度坐標系:BD-09,百度地圖所特有的坐標體系,它在火星坐標系的基礎上又進行了一次加密處理,
但是我們使用地圖的時候,卻又只能看到平面的地圖,因此,又有了另外一個概念:墨卡托投影,
墨卡托投影的主要功能,就是讓三維立體的地圖坐標能在二維平面上顯示,有點類似于《三體》里的二向箔的功能,把三維系統二維化,
二維化之后的平面,會被分割為一片一片的小圖,或者換句話說,由一片一片的小圖拼成了二維的地圖,而這個小圖,叫“瓦片圖”,這又是一個重要的概念,后文會繼續細說,
而瓦片圖的開始點(最左上角,或最左下角)在地球的什么地方呢,因為坐標系的不同,每個地圖可能也不一樣,所以,同一個經緯度,在不同的地圖平臺上,對應的瓦片圖的序號可能都是不一樣的,其中詳細的原理和規則演算法,這篇文章說得比較詳細:
國內主要地圖瓦片坐標系定義及計算原理
3.地圖平臺介紹
高德、百度、騰訊、谷歌地圖開放平臺介紹,
首先祭出開放平臺檔案,這是基于平臺開發的基礎:
高德地圖:https://lbs.amap.com/api/javascript-api/summary
百度地圖:https://lbsyun.baidu.com/index.php?title=jspopular3.0
騰訊地圖:https://lbs.qq.com/webApi/javascriptGL/glGuide/glBasic
谷歌地圖:https://developers.google.com/maps/documentation/javascript
每個地圖的API,大同小異,從細節來說,騰訊地圖的介面和高德地圖差別最小,
值得一提的是,在地圖上畫線(主要是導航的線路規劃標識),谷歌地圖沒有直接給出繪制虛線的介面,而國內的地圖平臺都有,這一點也體現了國內和國外的一種思維的差異,
另外還有一個細節,標注圖示旋轉(比如導航時,箭頭圖示跟隨人的方向旋轉)介面,高德地圖的旋轉的中心點不是圖示中心,而是圖示外層父元素的點位,因此轉向時,給人的感覺是自身的位置也在畫一個圓圈,而百度地圖沒有這個問題,當然這個問題也不是無法解決,我們可以通過自己撰寫轉向的CSS,利用JavaScript來控制圖示以中心點來轉向,

圖示圍繞父元素邊點轉向

圖示圍繞中心點正常轉向
每個地圖平臺在手機端的表現和體驗也有些差異,我個人覺得高德地圖最流暢順滑,百度地圖次之,
還有另外一點細節,就是關于瓦片圖(后文細說),一樣的圖,在騰訊地圖上會有非常細微的差別(騰訊地圖允許級別Zoom為小數,在兩個級別之間,還可以有多個過度值,而其他地圖只能是整數,這是一個更人性化的設計,但卻導致了瓦片圖變得模糊了一點),
4.瓦片圖覆寫到地圖上
瓦片圖是尺寸為256px*256px的正方形圖片,這樣的圖片,像瓦片蓋房一樣,覆寫為整個地圖,所以稱為“瓦片圖”,
瓦片圖的設計是一個非常精妙的設計,解決了地圖圖片太大的根本性問題,節約了服務器、客戶端設備的記憶體,按視覺范圍內加載圖片,也節約了網路流量,
這是一種前端的“懶加載”思想的體現,也是和前端的“雪碧圖”剛好相反的設計(關于“懶加載”和“雪碧圖”,這里不做過多介紹),
因此我們可以發現,不管什么解決方案,都有相應的使用場景,也有相反的局限性,不可脫離場景,一概而論,
瓦片圖覆寫到地圖,這是整個手繪電子地圖最核心、最基礎的設施和功能,因為此,我們自己繪制的精美地圖,才能夠覆寫到地圖平臺上,做成我們個性化需求的地圖,具體的實作,并沒有想象的那么復雜,當然,經驗豐富的程式員,可以設計出更科學的演算法和加載邏輯,這里拋磚引玉,做一個示例(高德地圖):
1 var fileHost = 'https://yourfilehost.com/';
2 var tileLayer = new AMap.TileLayer.Flexible({
3 createTile: function (x, y, zoom, success, fail) {
4 var imagePath = fileHost + '/tilefile/' + zoom + '/x + '_' + y + '.png';
5
6 var div = document.createElement('div');
7 var img = document.createElement('img');
8 img.onload = function () {
9 div.appendChild(img);
10 };
11 img.crossOrigin = "anonymous";
12 img.onerror = function () {
13 fail()
14 };
15 img.src = https://www.cnblogs.com/whatmiss/p/imagePath;
16
17 success(div);
18
19 }
20 });
21 tileLayer.setMap(map);
這里AMap.TileLayer.Flexible方法是核心,這是高德地圖提供的使用瓦片圖的一個介面,他提供了一個div層(className為“amap-layer amap-flexible”)覆寫在底圖之上,然后允許此方法回傳仁義的元素,填充在256*256的瓦片圖的方格里,因此,這里其實也可以更簡單的直接回傳一個img元素而不用div:
1 var fileHost = 'https://yourfilehost.com/';
2 var tileLayer = new AMap.TileLayer.Flexible({
3 createTile: function (x, y, zoom, success, fail) {
4 var imagePath = fileHost + '/tilefile/' + zoom + '/x + '_' + y + '.png';
5 var img = document.createElement('img');
6 img.onload = function () {
7 success(img);
8 };
9 img.crossOrigin = "anonymous";
10 img.onerror = function () {
11 fail()
12 };
13 img.src = https://www.cnblogs.com/whatmiss/p/imagePath;
14 }
15 });
16 tileLayer.setMap(map);
以上為高德地圖的示例,其他地圖原理相差不大,因此不再贅述,當然,這里只給了最基礎的加載瓦片圖的邏輯,事實上,根據實際情況,這里面還會做很多必要的其他業務邏輯的判斷,比如,系統應當存盤當前地圖的瓦片圖范圍,超出范圍的,就不要加載圖片,或者加載一張透明的小圖等,
這里列一下地圖平臺瓦片圖的介面名,便于有需要的搜索使用:
AMap.TileLayer.Flexible // 高德地圖
BMap.TileLayer // 百度地圖
TMap.ImageTileLayer // 騰訊地圖
google.maps.ImageMapType // 谷歌地圖
//需要注意的是,一些地圖的介面允許傳入引數:瓦片圖的尺寸,不過建議默認為256較好,畢竟這是通用的默認尺寸,
5.瓦片圖的制作
既然瓦片圖是基礎,那么我們如何從一張完整的手繪圖制作成為256*256的多張瓦片圖呢?可能設計師都能想到,直接用Photoshop切圖即可,很簡單,是的,常理來說是這樣,但這有2個問題:
(1)我們設計的圖,往往不是剛好為256px的倍數,那么第一張切圖,從什么地方開始?(即便是剛好為256的倍數,也不能從0像素開始切,后文細說)
(2)我們切圖出來之后,結合前文的地圖基礎知識,通過上面示例代碼可見,最關鍵的是每個圖的檔案名,要和地圖的級別Zoom、X軸的數值x、Y軸的數值y相對應,否則切出來的圖,沒有任何意義,
這兩個問題,是制作有用的瓦片圖的根本問題,
其實,在我們繪制手繪圖片檔案之前,就已經清晰的知道,我們繪制的內容到底是處于地圖的什么區域,然后應當記錄這個區域的起始點的經緯度,
前面說了瓦片圖可能從地圖的最左下角或左上角開始,具體情況是這樣的:高德、谷歌、騰訊地圖是從左下角,高德地圖是從左上角開始,
然后通過經緯度、抹卡托、可見區域像素三者的轉換演算法,計算出當前手繪圖分別在X軸和Y軸的第二張瓦片圖的偏移像素,然后從此像素位置開始切圖,并把計算得到的層級(Zoom)、X坐標(x)、Y坐標(y)的值作為對應的檔案名保存切圖,因此,說到這里,我們便都知道,這切圖作業沒辦法由設計師來人工執行,只能由設計的專門演算法的系統執行,
這里因為一些商業保密和其他的原因,我不能對這個切圖演算法做更仔細的講解,非常抱歉,
瓦片圖切好之后,放到專門的檔案服務器,然后前端代碼便可呼叫,實作瓦片圖覆寫于地圖底圖上展示,個性又漂亮的手繪地圖便基本成型了(如上圖“參考示例圖”),
6.動態規劃路徑的實作
漂亮個性的手繪電子地圖完成之后,這還只是一個純純的地圖展示,談不上功能性的使用,更別說“智慧”,因此,我們還需要增加各項智慧能力的功能,這其中,最基礎的又應當是“實時定位”及“動態路徑規劃”了,
其實這兩項功能,就是地圖APP的基礎的導航功能,但是因為大部分我們的園區內根本沒有地圖的路線,或者不全面,因此需要我們自己來實作這個功能,
具體如何實作,原理很簡單,前端通過定位介面獲取到用戶當前的位置(需要注意的是,為了支持更全面的使用場景,可以考慮兼容微信及HTML5原生介面),然后系統計算當前位置與指定的點位之間的路線,
因此,這就需要我們根據實際情況,事先在系統里標注園區內的點位和路線,路線越詳細越好,而通過這些點位和路線,要計算得到最短路徑,關鍵則在于最短路徑的“尋路演算法”,演算法可以自己設計,而目前很多偉大的科學家公開的很多最短路徑演算法則更為推薦,因為自己設計的演算法難免可能會出現一些不可預料的BUG,而這些公開的演算法經過嚴密的證明和大量使用的驗證,使得計算效率以及可靠性都有很好的保證,
這也是我的個人經驗,曾經我們自己設計的一個演算法,在大部分情況下都能計算出正確的最短路徑結果,但在某些情況下,卻得到意外的結果,或發生計算消耗較多時間,效率低下的情況,
我推薦“迪杰斯特拉”演算法,或“佛洛依德”演算法,
1 //C語言版本的迪杰斯特拉演算法
2 int a[1000][1000];
3 int d[1000];//d表示源節點到該節點的最小距離
4 int p[1000];//p標記訪問過的節點
5 int i, j, k;
6 int m;//m代表邊數
7 int n;//n代表點數
8 int main()
9 {
10 scanf("%d%d",&n,&m);
11 int min1;
12 int x,y,z;
13 for(i=1;i<=m;i++)
14 {
15 scanf("%d%d%d",&x,&y,&z);
16 a[x][y]=z;
17 a[y][x]=z;
18 }
19 for( i=1; i<=n; i++)
20 d[i]=max1;
21 d[1]=0;
22 for(i=1;i<=n;i++)
23 {
24 min1 = max1;
25 for(j=1;j<=n;j++)
26 if(!p[j]&&d[j]<min1)
27 {
28 min1=d[j];
29 k=j;
30 }
31 p[k] = 1;
32 for(j=1;j<=n;j++)
33 if(a[k][j]!=0&&!p[j]&&d[j]>d[k]+a[k][j])
34 d[j]=d[k]+a[k][j];
35 }
36 for(i=1;i<n;i++)
37 printf("%d->",d[i]);
38 printf("%d\n",d[n]);
39 return 0;
40 }
當然這些公開演算法,都是最基本的核心和原理,要能讓我們可在地圖上做最短路徑尋找,還需要我們自己根據實際業務和邏輯,做相應的變種,
根據對當前用戶的實時定位,通過最短路徑演算法,便能實作動態路徑的規劃,這便使得我們的手繪電子地圖具備了最基礎、最重要的導航功能,
7.自動觸發的實作
通過實時定位獲取到用戶當前位置,系統判斷位置是否和后臺設定的點位接近,當距離已小于設定值的時候,電子地圖系統便自動展示當前點位的介紹資訊、語音講解,或者商家推送的優惠券等,因此,我們的電子地圖系統便越來越智能了,
而在此基礎之上,我們可以相當的所有功能,都可以加載到電子地圖系統上,由此我們的系統便優化成為真正的“智慧導覽系統”,其他的更多的功能的實作,我便不再贅述,只對下列三個比較特別的功能再做一些簡述,
8.多語言的實作
多語言是一個老生常談的需求,也是一個系統國際化所必備的功能,對于智慧導覽系統而言,我覺得有兩個值得注意的點:
(1)地圖本身的文案,包括提示資訊、按鈕文字等,這可以在代碼層面做多語言的配置,
(2)地圖示注點位相關的內容,包括圖文介紹、語音講解等內容,這里需要在后臺系統設計可添加多語言內容的管理,
9.實作國內國外可同時訪問地圖
這一點需求,是根據實際情況來提的,因為國內和國外的地圖基本上不能互通,因此我們的智慧導覽系統應當解決這一痛點,
10.地圖路線的采集和標注
系統的“動態路徑規劃”功能需要園區的路線資料為基礎,因此系統應當提供路線采集和標注的配套工具,方便作業人員從現場采集路線的經緯度等資訊,
五、結尾
本文是我個人基于“智慧導覽系統”開發經驗的一個大致的概括,整體來講,寫得比較粗陋和簡略,很難作為一個方案或者教程,只當是我個人做一個總結罷了,如有不當之處,歡迎指正,也歡迎有興趣的一起討論,
體驗地圖 ?作者:z281099678 歡迎來一起溝通探討,轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/501839.html
標籤:其他
下一篇:前端須知的 Cookie 知識
