百度地圖API目前在地圖API領域越來越受到眾多開發者的關注,許多應用都使用到了百度地圖API服務,包括博主me,我自己使用做的是Javascript API,根據經驗,我想整理出一份系列教程,如果能給想使用百度地圖API的開發者帶來一點幫助的話,那就太好了,也希望大家能夠互相交流,共同學習。

寫在前面的話:如果各位真的想深入瞭解地圖的JSAPI,首先一些基礎的GIS概念必不可少,GIS就是地理資訊系統,可能很多程式猿沒聽過,簡單地說,GIS就是通過計算機軟體技術將地理資訊進行視覺化管理,地圖就是一個最重要的地理資訊應用。涉及到地圖的GIS基礎概念,首先有投影、座標系、座標轉換、瓦片圖和向量圖。先不要暈,更復雜還在後面呢。

  現在很多網路地圖都是使用Web墨卡託投影當做主要的投影方法,包括Google Map和百度地圖,具體的投影原理和方法這裡就不腦補了。百度百科就解釋的很清楚。想了解細節的可以去深入挖掘。投影的目的就是講球面的形狀顯示在平面的顯示器上形成地圖,投影之後的地圖就有自己的座標系統。比如很多人都知道的經緯度座標系來描述地球上的某一位置。而百度地圖API中的涉及到的座標系就不僅僅只有經緯度座標系了。

  你需要了解到以下的座標系:

  • 經緯度:通過經度緯度來描述某一點位置。如BMap.Point(116.404, 39.915)。注意:一般GPS裝置獲取的經緯度屬於WGS84座標系。在國內地圖廠商使用的經緯度座標都不是WGS84經緯度座標,都是經過gc02加密之後的。而百度地圖在gc02加密的基礎上又進行一次bd09加密。所以使用原始GPS獲取的經緯度直接在百度地圖上進行打點的話就會有偏移。使用原始的GPS經緯度座標在地圖上打點需要先呼叫百度地圖的Geoconv API 對原始座標進行座標轉換。傳送門:座標轉換API
  • 平面座標:球面的形狀通過投影變換成平面上的形狀,在平面,就需要一個平面座標系來描述某一個位置,百度地圖API預設使用墨卡託投影。投影之後就有一個平面座標系。在百度地圖API中,平面座標就是想象成把球形展開在一張平面上,座標原點和經緯度原點一致,赤道和0度經線相交的位置。百度地圖API將地圖分為了18個級別,平面座標是以最大的級別18級為準的,也就是說在18級下,平面座標的一個單位就代表了螢幕上的1個畫素。平面座標與地圖所展示的級別沒有關係,也就是說在1級和18級下,天安門位置的平面座標都是一致的。那麼如何知道某個位置的平面座標呢?可通過BMap.MercatorProjection類來完成,該類提供經緯度與平面座標互相轉換的方法。例如天安門的經緯度大約為116.404, 39.915,經過轉換即可得到平面座標:
     var projection =new BMap.MercatorProjection();
    var point = projection.lngLatToPoint(new BMap.Point(116.404, 39.915));
    alert(point.x +", "+ point.y);

    最後得到的結果就是:12958175,4825923.77。

  • 畫素座標:畫素座標表示的是在某一縮放級別下位置的顯示座標,在18級別下,畫素座標可以通過將平面座標向下取整得到,對,畫素座標都是整數值。因為它代表中螢幕上的畫素值。在其他的級別下,我們可以使用如下公式獲取畫素座標。
    畫素座標 = Math.floor(平面座標 * 2zoom-18)
  • 圖塊座標:百度地圖API在網頁上顯示地圖的時候是將整個地圖切分成若干塊地圖瓦片來顯示的,每一個地圖顯示級別都包含若干塊瓦片圖。圖塊座標表示的就是某一級別下的某一張瓦片圖,有三個屬性,x, y, z。z表示縮放級別。x,y 表示座標。x,y的計算如下所示:
    圖塊座標 = 畫素座標 / 256
    因為百度地圖中每一張瓦片圖的大小都是256*256的。所以畫素座標/256就可以得到需要在平面上顯示的圖塊座標了。下面一張圖或許更容易理解。                             
    還是以畫素座標原點(等於平面座標原點)以基準,先計算畫素座標值,然後再計算得到點所在的圖塊座標。注意,不同的縮放級別下,相同的點所在的圖塊座標是不一樣的。
  • 可視區座標:這個座標肯定是大家會經常用到的,它就是相對於你的地圖容器的座標,地圖容器就是初始化地圖的時候傳入的Dom元素,原點是這個Dom元素的左上角,在實際的開發過程中,可以使用API中的Map類的pointToPixel和PixelToPoint方法將經緯度和可視區座標進行相互轉化。
  • 覆蓋物座標:這個座標相對來說使用的場景較少,覆蓋物在實現上就是若干DOM元素,這些元素會被放在若干覆蓋物容器內,那麼覆蓋物的座標實際上就是相對於這些覆蓋物容器的座標。在地圖初始化完成後,覆蓋物容器的左上角與地圖可視區域左上角位置相同,一旦地圖被移動、縮放,覆蓋物容器位置就會發生變化。在自定義覆蓋物的時候API提供經緯度資訊,而開發者需要自行將經緯度轉換為覆蓋物的畫素座標,從而覆蓋物才能顯示在正確的位置上。可以使用API中的Map類的pointToOverlayPixel和overlayPixelToPoint兩個方法來實現。

這些座標系統,在地圖API開發中肯定會經常用到,如果對這些基礎概念不是很瞭解的話可能有時候就會產生疑惑,甚至在一些功能開發上找不到思路。如果深入理解了基礎概念,那麼在使用地圖API開發的過程中就能夠熟練的運用API提供的一些方法。

說了這麼多,來個程式碼示例給大家回顧一下概念:

 <!DOCTYPE html>
<html> <head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<title>Map Coordinate</title>
<style type="text/css">
/*<![CDATA[*/ html {
height: 100%;
}
body {
height: 100%;
margin: 0px;
padding: 0px;
}
#map_container {
height: 100%;
}
/*]]>*/
</style> </head> <body>
<div id="map_container"></div>
</body>
<script type="text/javascript" src="http://api.map.baidu.com/api?v=2.0&ak=wWy2A8K94nhntYTYUHS19RXW"></script>
<script type="text/javascript">
var mp = new BMap.Map('map_container', {
enableHighResolution: true
});
mp.centerAndZoom('北京', 15);
mp.enableScrollWheelZoom(); var TILE_SIZE = 256; mp.addEventListener('click', function(e) {
var info = new BMap.InfoWindow('');
var pos = e.point;
var projection = this.getMapType().getProjection();
var lngLatStr = "經緯度:" + pos.lng + ", " + pos.lat;
var worldCoordinate = projection.lngLatToPoint(pos);
var worldCoordStr = "<br />平面座標:" + worldCoordinate.x + ", " + worldCoordinate.y;
var pixelCoordinate = new BMap.Pixel(Math.floor(worldCoordinate.x * Math.pow(2, this.getZoom() - 18)),
Math.floor(worldCoordinate.y * Math.pow(2, this.getZoom() - 18)));
var pixelCoordStr = "<br />畫素座標:" + pixelCoordinate.x + ", " + pixelCoordinate.y;
var tileCoordinate = new BMap.Pixel(Math.floor(pixelCoordinate.x / 256),
Math.floor(pixelCoordinate.y / 256));
var tileCoordStr = "<br />圖塊座標:" + tileCoordinate.x + ", " + tileCoordinate.y;
var viewportCoordinate = mp.pointToPixel(pos);
var viewportCoordStr = "<br />可視區域座標:" + viewportCoordinate.x + ", " + viewportCoordinate.y; var overlayCoordinate = mp.pointToOverlayPixel(pos);
var overlayCoordStr = "<br />覆蓋物座標:" + overlayCoordinate.x + ", " + overlayCoordinate.y; info.setContent(lngLatStr + worldCoordStr + pixelCoordStr + tileCoordStr +
viewportCoordStr + overlayCoordStr);
mp.openInfoWindow(info, pos);
});
</script> </html>

瀏覽器執行,然後滑鼠點選地圖上某一位置後,彈框如下:

結語:在使用百度地圖API開發的過程中,座標系的概念非常重要,因為涉及到在地圖上顯示,而很多時候開發者拿到的座標都是經緯度座標,甚至都是GPS座標,這些座標資料要想在百度地圖上標註出正確的位置,一定要記的按照上述的座標系概念進行轉換。要不然結果是不準確的。好了,後續,我會陸續發出關於如何使用地圖API開發,介紹百度地圖API的一些js原理的系列文章。