我眼中的高德Map ABC企業(yè)級(jí)地圖
- 來(lái)源:中國(guó)信息化周報(bào) smarty:if $article.tag?>
- 關(guān)鍵字:漏洞,博客,高德地圖 smarty:/if?>
- 發(fā)布時(shí)間:2015-03-20 15:29
Map ABC與a map
走在大街小巷,或是瀏覽電視節(jié)目,我們常會(huì)看到高德地圖的廣告,有心人會(huì)發(fā)現(xiàn)高德地圖標(biāo)識(shí)是a map,而在百度搜索中搜尋“高德地圖”,偶爾也會(huì)看到Map ABC的網(wǎng)站, 進(jìn)入網(wǎng)頁(yè)就會(huì)發(fā)現(xiàn)a map和Map ABC的網(wǎng)站截然不同,它們之間并非“李逵”和“李鬼”,而是同屬于高德公司,有著千絲萬(wàn)縷的聯(lián)系。首先來(lái)了解下a map,a map最開始是由Map ABC的手機(jī)端產(chǎn)品迷你地圖演變而來(lái),開始叫高德地圖,目前作為高德旗下的移動(dòng)事業(yè)部。主要運(yùn)營(yíng)高德地圖,2012年初開始上線PC端地圖,并開放API接口,未來(lái)的定位是運(yùn)營(yíng)的模式,提供服務(wù),主打免費(fèi)模式,跟百度地圖,谷歌地圖一樣,經(jīng)過(guò)市場(chǎng)變革,a map更加偏向移動(dòng)端應(yīng)用程序以及API的提供;而Map ABC雖然同屬高德旗下產(chǎn)業(yè),但是定位于企業(yè)服務(wù)。主要是針對(duì)企業(yè)級(jí)用戶以及行業(yè)應(yīng)用,針對(duì)不同行業(yè)的特別為其開發(fā)個(gè)性化的地圖服務(wù)。以滿足各行業(yè)對(duì)地圖的深層次應(yīng)用,如個(gè)性化地圖服務(wù),物流行業(yè)的SAAS應(yīng)用等,經(jīng)過(guò)市場(chǎng)變革,逐漸淘汰了包括Sliver light和Flash在內(nèi)的API,保留下JS和Flex的API,并逐漸向移動(dòng)端(Android及IOS)傾斜,成為主打移動(dòng)端的多平臺(tái)地圖服務(wù)廠商。
初識(shí)地圖——簡(jiǎn)單的功能
一個(gè)地圖服務(wù)之所以被稱之為地圖服務(wù),是因?yàn)樗鼭M足人們使用所需的各種功能,無(wú)論是使用移動(dòng)設(shè)備、平板電腦、筆記本電腦或是臺(tái)式機(jī),流暢的拖動(dòng)地圖、快速的定位與查詢是地圖服務(wù)最基本的配置,例如:我們尋找一家餐廳,在地圖上輸入餐廳的名稱,地圖快速定位到該餐廳所在位置,我們可以拖動(dòng)地圖查看周邊的標(biāo)志性建筑以便前往,這就是地圖帶給用戶最直觀的體驗(yàn)之一。以Map ABC地圖為例,當(dāng)你在瀏覽地圖時(shí),地圖上絕不會(huì)是白茫茫的一片,而是有山有海有河流有國(guó)界,放大地圖甚至可以看到省、市邊界、道路網(wǎng)等等,這些信息都是通過(guò)圖層展現(xiàn)出來(lái),所謂圖層,維基百科給的解釋是:圖層是應(yīng)用在圖像編輯軟件上的概念,圖層就像一層層相疊,但彼此獨(dú)立的的透明底片,其好處是,在一個(gè)圖層上繪制及編輯的物件,并不會(huì)影響另一個(gè)圖層上的物件。所以我們就知道地圖圖層是將一個(gè)個(gè)地圖中的內(nèi)容疊加從而展現(xiàn)給用戶,這么多內(nèi)容,如果在用戶打開時(shí)直接加載進(jìn)來(lái)勢(shì)必會(huì)導(dǎo)致用戶流量瘋狂上漲,而且在加載完成前不會(huì)顯示地圖,Map ABC做的很好,將一整張地圖分隔成若干個(gè)小圖片,平緩的加載進(jìn)網(wǎng)頁(yè),為用戶提供了良好的體驗(yàn)環(huán)境。
有了地圖,只能說(shuō)有了界面,地圖還要能拖動(dòng)、放大、縮小。那么,讓我們先來(lái)看什么是地圖拖動(dòng)?把一張圖片從左拖到右?亦或是圖片過(guò)大,通過(guò)拖動(dòng)來(lái)看到全部?這些是我原來(lái)的想法,但現(xiàn)在我要說(shuō)的都不是這些,至少在我看過(guò)了Map ABC的拖動(dòng)后是這樣認(rèn)為的,Map ABC地圖采用“無(wú)極”拖動(dòng),無(wú)論是從右向左還是從左向右,永遠(yuǎn)不會(huì)拖動(dòng)到終點(diǎn),像一個(gè)筒狀結(jié)構(gòu),當(dāng)你覺得到終點(diǎn)時(shí),又會(huì)轉(zhuǎn)回到起點(diǎn)(注:“無(wú)極”拖動(dòng)曾出現(xiàn)過(guò)Bug,即拖動(dòng)地圖一圈后回到原點(diǎn),但是之前添加的對(duì)象會(huì)消失不見,該Bug已被修復(fù))。
大部分地圖應(yīng)用程序都是二次開發(fā)人員基于地圖服務(wù)API開發(fā)出來(lái)的,Map ABC提供了地圖的展現(xiàn),接下來(lái)就該由開發(fā)人員使用其中的接口進(jìn)行開發(fā)了,API應(yīng)當(dāng)提供包含點(diǎn)、線、面在內(nèi)的基礎(chǔ)對(duì)象模型,提供關(guān)于基礎(chǔ)對(duì)象在地圖中的添加、編輯、刪除等操作,而Map ABC Flex版API提供了10類覆蓋物對(duì)象,分別為:面類、圓類、背景圖片類、文字標(biāo)簽類、點(diǎn)標(biāo)注類、覆蓋物基類、多邊形類、折線類、雷達(dá)標(biāo)注類、矩形類,Map ABC其他版本API無(wú)出其右。10種對(duì)象其實(shí)并不多,實(shí)際上,開發(fā)中用到的會(huì)更少一些,主要是面、圓、文字、點(diǎn)、多邊形和折線,例如:大眾點(diǎn)評(píng)網(wǎng)的每家商戶頁(yè)面都有一個(gè)小地圖,地圖中只有一個(gè)點(diǎn)對(duì)象,標(biāo)注了商戶所在位置。這是最簡(jiǎn)單的應(yīng)用,當(dāng)然,真正去做二次開發(fā)所實(shí)現(xiàn)的功能一定會(huì)復(fù)雜的多。
地圖進(jìn)階——復(fù)雜的功能
什么是在地圖上實(shí)現(xiàn)復(fù)雜的功能?更多的點(diǎn)、更多的線、更多的對(duì)象?但這只是復(fù)雜功能中的一部分,由于B/S結(jié)構(gòu)下在地圖添加大量覆蓋物(或稱密集覆蓋物)勢(shì)必會(huì)使瀏覽器所占內(nèi)存飆升,因此這種方法也是檢驗(yàn)地圖服務(wù)是否優(yōu)秀的手段之一,作者在接觸Map ABC Flex版之前使用過(guò)Super Map Desk pro.Net 6(這是超圖公司早期的軟件,嚴(yán)格說(shuō)起來(lái),該軟件并不算地圖服務(wù),主要是測(cè)繪、航拍、建模等作圖功能,同時(shí)不提供地圖,用戶使用時(shí)需要自己配置地圖),在地圖上添加將近三百條線段的時(shí)候,瀏覽器開始崩潰,而使用Map ABC做這樣一個(gè)程序:在指定范圍內(nèi),每隔5秒隨機(jī)生成2000個(gè)點(diǎn)。雖然內(nèi)存會(huì)上漲,但頁(yè)面顯示依然流暢。但是如果在隨機(jī)生成2000個(gè)點(diǎn)的同時(shí)分配監(jiān)聽事件,這個(gè)程序的效率將會(huì)直線下降,時(shí)間越長(zhǎng),效率越低,雖然不至于瀏覽器崩潰,但是在拖動(dòng)地圖時(shí)卡頓感明顯增強(qiáng),這是因?yàn)檫^(guò)多的監(jiān)聽事件以及頻繁的監(jiān)聽會(huì)使地圖負(fù)荷增大,如果不能及時(shí)釋放資源,內(nèi)存占用量就會(huì)越來(lái)越大。為了最大程度解決這種大數(shù)據(jù)量的展示,API里提供了點(diǎn)聚合功能,用于海量數(shù)據(jù)的展示,點(diǎn)聚合的效果體現(xiàn)在不同地圖級(jí)別下將自動(dòng)根據(jù)地圖上點(diǎn)的密集程度將密集度大的區(qū)域聚合成一個(gè)點(diǎn),這個(gè)被聚合成的點(diǎn)將顯示該區(qū)域內(nèi)點(diǎn)的數(shù)量,如果地圖在極大比例下是有可能將2000個(gè)點(diǎn)聚合成一個(gè)點(diǎn)的,點(diǎn)聚合解決了海量數(shù)據(jù)視覺效果混亂的劣勢(shì)并在一定程度上提升了密集點(diǎn)下程序的效率(我之所以只說(shuō)在“一定程度上”,是因?yàn)榧幢闶褂命c(diǎn)聚合,也只是隱藏點(diǎn),而不是銷毀點(diǎn),點(diǎn)的屬性和事件依舊存在,只是不可見而已)。而二次開發(fā)人員能夠做的也只是及時(shí)的銷毀不用的對(duì)象而已,是無(wú)法從地圖內(nèi)部進(jìn)行深層次的優(yōu)化的。
我認(rèn)為在使用API中提供的功能,除去對(duì)點(diǎn)、線、面以及地圖本身的基本操作功能外,其他功能應(yīng)當(dāng)都屬于復(fù)雜功能,Map ABC官方示例中列舉了10大項(xiàng)共計(jì)57個(gè)示例(Js版本的API中分類更加詳細(xì)),其中包含右鍵菜單、GPS應(yīng)用示例、疊加層示例、地圖工具示例、鼠標(biāo)工具示例、海量數(shù)據(jù)展示在內(nèi)的六項(xiàng)應(yīng)當(dāng)都屬于復(fù)雜功能,這些功能為用戶深度開發(fā)地圖應(yīng)用提供了良好的接口。
我曾使用API中的GPS功能開發(fā)了基于Map ABC Flex版的定位系統(tǒng)(API的實(shí)例展示了實(shí)時(shí)追蹤和軌跡回放,但我發(fā)現(xiàn),這兩個(gè)功能其實(shí)是一樣的,不得不說(shuō)這是API中的一大敗筆),這個(gè)功能就是GPS功能的深度開發(fā),實(shí)際上,由于速度的不可控性,我放棄了實(shí)例中實(shí)時(shí)追蹤的平滑顯示的方式,改為用單點(diǎn)顯示并顯示歷史軌跡,在速度不過(guò)快的時(shí)候,是可以模擬出平滑效果的。而歷史回放則沿用API中軌跡回放的效果。再如疊加層功能,因?yàn)轫?xiàng)目需求的地圖效果與默認(rèn)的地圖效果不符,所以我使用一張白色地圖作為底圖,在上面疊加自定義的圖層,呈現(xiàn)出一個(gè)完全不同于默認(rèn)地圖的效果圖(疊加圖層的文件必須是一張地圖,個(gè)人用戶基本不具備制作該地圖的環(huán)境,我也是通過(guò)Map ABC官方提出的需求,由他們負(fù)責(zé)制作,因此,疊加層功能不建議輕易嘗試)。我之所以將這兩個(gè)經(jīng)歷拿出來(lái)作為例子,是想說(shuō)使用API中復(fù)雜功能不同于基礎(chǔ)功能,復(fù)雜功能更加細(xì)致,使用者需要對(duì)地圖的了解有一定基礎(chǔ)才能很好的掌控復(fù)雜功能,同時(shí),單獨(dú)使用復(fù)雜功能會(huì)令人匪夷所思,因?yàn)槠涔δ艿尼槍?duì)性更強(qiáng),往往只為某一些特定需求提供服務(wù),例如海量數(shù)據(jù)中的點(diǎn)聚合功能針對(duì)大數(shù)據(jù)量覆蓋物的密集分布,如果僅僅是數(shù)十個(gè)點(diǎn),完全沒有必要使用,所以使用復(fù)雜功能進(jìn)行深入開發(fā)時(shí)一定要有對(duì)應(yīng)的使用環(huán)境。
“看不見的功能”
Flash有些功能并不是原生API里就提供的,需要二次開發(fā)人員對(duì)原生API進(jìn)行擴(kuò)展,我稱這些被擴(kuò)展出的功能為“看不見的功能”。擴(kuò)展出的功能可能千奇百怪,各不相同,無(wú)法一一列舉,因此,我只舉一些可能較為常用的加以說(shuō)明。
為什么我們要對(duì)原生API進(jìn)行擴(kuò)展?一個(gè)再完善的API也不可能面面俱到,滿足所有開發(fā)者的需求,別人開發(fā)的地圖應(yīng)用里有框體拖動(dòng)效果、有畫半圓的效果,而Map ABC的原生API是不提供這種效果的,怎么辦?當(dāng)然不能就這么算了,所以需要對(duì)原生API進(jìn)行擴(kuò)展,比如框體拖動(dòng)效果是指存在一個(gè)信息框體,該框體內(nèi)信息指向地圖中的某一個(gè)特定覆蓋物,顯示該覆蓋物的詳細(xì)信息,我們不希望這個(gè)框體只能僵硬的放在相對(duì)于這個(gè)覆蓋物的特定位置,它應(yīng)當(dāng)是可以拖動(dòng)的,應(yīng)當(dāng)有一根細(xì)線用來(lái)連接覆蓋物和信息框,以便告知用戶該信息框體是屬于這個(gè)覆蓋物的,那么如何來(lái)做?百度?我也經(jīng)常百度,但顯然對(duì)于這個(gè)問(wèn)題是百度不出任何可用的結(jié)果的,那么只好自己來(lái)解決,要實(shí)現(xiàn)這個(gè)效果首先要有三個(gè)對(duì)象:覆蓋物對(duì)象、線對(duì)象、框體對(duì)象,兩點(diǎn)可以確定一條直線,覆蓋物對(duì)象與框體對(duì)象無(wú)論怎么移動(dòng),它們的經(jīng)緯度以及x,y坐標(biāo)是可以確定的。如果覆蓋物對(duì)象移動(dòng)了,可以知道與上一次位置的偏移量,根據(jù)偏移量就可以確定線對(duì)象以及框體對(duì)象的新位置;如果框體對(duì)象被拖動(dòng)了,那么可以知道框體對(duì)象被放下的位置,更新線對(duì)象的坐標(biāo)即可,至此,對(duì)象間的組合已完成,三個(gè)對(duì)象已經(jīng)形成一個(gè)聯(lián)動(dòng)的整體,但是這并不算完,因?yàn)檫€沒有將地圖考慮在內(nèi),點(diǎn)對(duì)象和線對(duì)象是地圖原生API的內(nèi)置對(duì)象,但是框體不是,所以必須在地圖移動(dòng)的時(shí)候動(dòng)態(tài)更新框體位置以模擬出框體隨著地圖的移動(dòng)而移動(dòng),這需要使用Map Mouse Event中的地圖事件。
原生API中提供了畫圓的方法,里面有很多方法:二態(tài)性、大小、偏移、透明度、色值等等,但是遍尋API,一定不會(huì)找到畫半圓或四分之一圓的方法,這個(gè)時(shí)候百度依然不是萬(wàn)能的,只好自己來(lái)實(shí)現(xiàn),我們可以將圓描繪成點(diǎn),點(diǎn)與點(diǎn)間用直線相連,如果點(diǎn)足夠密集,完全可以模擬出一個(gè)圓,同理也可以模擬出半圓,至于方法就需要用到數(shù)學(xué)里的根據(jù)圓心、半徑以及夾角計(jì)算出圓上任一點(diǎn)坐標(biāo)。
之所以列舉上述兩個(gè)方法,是因?yàn)樗鼈儤O具代表性,框體拖動(dòng)效果完全基于API原生方法中的對(duì)象進(jìn)行組合,并使用事件控制組合后的對(duì)象,協(xié)調(diào)其內(nèi)部不同對(duì)象間的同步;而畫半圓的方法則是脫離原生API中畫圓方法,通過(guò)使用足夠多的基礎(chǔ)點(diǎn)對(duì)象描繪出半圓形狀,再進(jìn)行繪制。所以說(shuō),原生API中不提供方法并不能成為一個(gè)二次開發(fā)者無(wú)法實(shí)現(xiàn)功能的借口,也許,這個(gè)功能只是“看不見”而已呢?
地圖中存在的漏洞
漏洞是伴隨著應(yīng)用程序而生,因此我們只能盡力去消除它,我曾在我發(fā)表的一篇博客中列舉了至今為止我發(fā)現(xiàn)的所有原生API中的漏洞,不過(guò),我在這里不打算將它們?nèi)繌?fù)述一遍,而是只挑出其中一些常見的漏洞來(lái)告知讀者,希望今后在遇到的時(shí)候能夠以人為的方法去修補(bǔ)和跳過(guò)這些漏洞。
1、tip功能是指覆蓋物彈出的信息窗口,其支持open tip和close tip,即窗口打開/關(guān)閉事件,但是close tip在第一次使用的時(shí)候會(huì)觸發(fā)open tip事件,也就是想要關(guān)閉就必須得打開一次,這樣兩個(gè)事件就相互重復(fù)了,但是如果第二次使用close tip就不會(huì)出現(xiàn)這種錯(cuò)誤。
解決辦法 第一次觸發(fā)點(diǎn)擊操作時(shí),注銷tip close事件或者不注冊(cè)tip close事件。增加一全局變量isFirst標(biāo)注是否是第一次click事件觸發(fā),如果是第一次加載,就不處理tip close事件,如果不是,就處理tip close事件。但是我建議拋棄tip功能,tip功能的可重寫性不高, 所以盡量自己去寫類似tip這種鼠標(biāo)移上彈出的功能, 可操作性比較好。
2、pan To和zoom In事件,一個(gè)是將地圖移動(dòng)到當(dāng)前點(diǎn),一個(gè)是放大地圖,單獨(dú)用都沒有問(wèn)題,但是一旦兩個(gè)連接起來(lái)用就會(huì)發(fā)現(xiàn)pan To在第一次點(diǎn)擊的時(shí)候不起作用。
解決辦法 只能是再點(diǎn)一次了,還有一種辦法就是在pan To和zoomIn中間加入間隔時(shí)間:flash.utils.setTimeout(zoom,2000)。
3、軌跡回放,對(duì)覆蓋物使用用戶定義的圖片時(shí),放大縮小地圖都會(huì)導(dǎo)致覆蓋物不隨地圖縮放級(jí)別變化而變化。
解決辦法 使用API中默認(rèn)的圖標(biāo),如果需求使用自定義圖片,尚無(wú)好的解決方案。
4、疊加圖層和地圖監(jiān)聽事件有沖突。不能把地圖監(jiān)聽事件(比如zoom事件)放在疊加圖層添加事件前面執(zhí)行(map Obj.add Tile Layer(tilelayer);),這樣會(huì)導(dǎo)致監(jiān)聽事件失效。
解決辦法避免這種情況發(fā)生需要先添加完所有疊加圖層,然后再一個(gè)個(gè)的添加地圖事件。
經(jīng)驗(yàn)之談
現(xiàn)在,我仍然會(huì)參考API手冊(cè)中的示例代碼,不是因?yàn)椴粫?huì)寫,而是因?yàn)槲臋n中的示例代碼非常規(guī)范,聲明與調(diào)用邏輯性很強(qiáng),即便是面對(duì)一些屬性繁多的對(duì)象,文檔示例也會(huì)按順序、按分類去調(diào)用。但是即便手冊(cè)示例再多,再詳細(xì)也很難涵蓋用戶在使用過(guò)程中遇到的一切情況,我很想把自己的體會(huì)完全寫出來(lái),這樣讀者在看完文章后就能完全明白API中所有的方法,但礙于篇幅,我只將一些自己認(rèn)為比較重要的經(jīng)驗(yàn)和教訓(xùn)羅列一下。
1、MQLngLat方法構(gòu)造一個(gè)經(jīng)緯度對(duì)象,一定要記住參數(shù)lng是經(jīng)度,參數(shù)lat是緯度,經(jīng)緯度寫反地圖是不會(huì)報(bào)錯(cuò)的,只是會(huì)超出地圖范圍,顯示在地圖以外的地方,這就造成用戶會(huì)以為設(shè)置的經(jīng)緯度沒有起作用,然后不停的去檢查自己的添加覆蓋物代碼。
2、動(dòng)態(tài)更新覆蓋物方法update Overlay,在API的幫助文檔里該方法被解釋成更新覆蓋物信息,無(wú)法對(duì)對(duì)象的經(jīng)緯度信息進(jìn)行更新。這里一定是注意的是,該方法無(wú)法更新點(diǎn)類型的覆蓋物經(jīng)緯度,而對(duì)線對(duì)象、多邊形對(duì)象是可以進(jìn)行更新的。
3、地圖提供remove Overlay方法去移除已存在的覆蓋物,但是請(qǐng)注意,在移除對(duì)象后,請(qǐng)對(duì)內(nèi)存進(jìn)行回收,地圖是非常占用內(nèi)存的,覆蓋物也一樣。
4、當(dāng)我們?yōu)橐粋€(gè)地圖覆蓋物對(duì)象添加監(jiān)聽事件時(shí),請(qǐng)確保這個(gè)對(duì)象已經(jīng)被添加進(jìn)地圖,否則是會(huì)報(bào)錯(cuò)的。另外,無(wú)法在當(dāng)前對(duì)象的監(jiān)聽事件里對(duì)這個(gè)對(duì)象進(jìn)行動(dòng)態(tài)更新的。
5、每個(gè)覆蓋物都可以設(shè)置label文本框,但是無(wú)法對(duì)文本框進(jìn)行更新,想要更新文本框,可以單獨(dú)創(chuàng)建一個(gè)M label地圖文本框?qū)ο?,它是可以跟隨覆蓋物并進(jìn)行更新的。
6、地圖坐標(biāo)與平面坐標(biāo)是兩個(gè)完全不相同的概念,切勿將其混淆,地圖坐標(biāo)是指經(jīng)緯度坐標(biāo),平面坐標(biāo)是指屏幕容器內(nèi)的坐標(biāo),雖然API中提供了轉(zhuǎn)換方法from LngLat To Container Pixel和from Container Pixel To LngLat,但是這里仍要提醒使用者,在對(duì)基于地圖的對(duì)象進(jìn)行定位請(qǐng)使用地圖坐標(biāo),對(duì)地圖中的非地圖對(duì)象操作請(qǐng)將地圖坐標(biāo)轉(zhuǎn)換為平面坐標(biāo)。如果希望自己進(jìn)行手動(dòng)轉(zhuǎn)換,請(qǐng)使用WGS84坐標(biāo)系。
7、使用Map ABC自帶的全屏后,是無(wú)法與后臺(tái)交互的,Map ABC全屏機(jī)制其實(shí)就是flex中的全屏機(jī)制,flex的全屏在文本框內(nèi)輸入信息遞交表單后是無(wú)法與后臺(tái)進(jìn)行操作的,也就是全屏后前后臺(tái)的交互被隔絕了,但是自動(dòng)執(zhí)行的行為還在,所以在全屏后盡量不要再有遞交表單等行為的出現(xiàn)。
以上所寫的這些經(jīng)驗(yàn)和教訓(xùn)并不多,對(duì)于整個(gè)API來(lái)說(shuō)甚至可以稱得上是“滄海一粟”,但我覺得這些問(wèn)題很可能會(huì)令開發(fā)者困守一隅,卻找不到解決問(wèn)題的出路,因此將它們羅列出來(lái),希望讀者能有所收獲,并在之后的開發(fā)工作中獲得便利。
寫在最后
盡管Map ABC官方基本停止了對(duì)Flex版API的更新,但我仍然堅(jiān)守著、不停的對(duì)其進(jìn)行二次開發(fā),畢竟這是我的工作,而這篇文章盡管非常的言簡(jiǎn)意賅,卻是我的經(jīng)驗(yàn)之談,也是用成千上萬(wàn)行代碼換來(lái)的。我希望能通過(guò)這篇文章讓后來(lái)者們對(duì)他們即將碰觸的地圖有一個(gè)大致的了解,多一個(gè)通向精通API的捷徑。
民航電信開發(fā)有限責(zé)任公司 江麟
