在百度地圖API中,你須要瞭解以下座標系:javascript
經緯度:經過經度(longitude)和緯度(latitude)描述的地球上的某個位置。
平面座標:投影以後的座標(用x和y描述),用於在平面上標識某個位置。
像素座標:描述不一樣級別下地圖上某點的位置。
圖塊座標:地圖圖塊編號(用x和y描述)。
可視區域座標:地圖可視區域的座標系(用x和y描述)。
覆蓋物座標:覆蓋物相對於容器的座標(用x和y描述)。html
別被這麼多的座標系嚇着,看完了後面的講解相信你會逐漸理解它們。java
經緯度
這個就很少說了,不熟悉的能夠翻翻地理書。但須要注意的是即使同是經緯度座標也可能屬於不一樣的座標體系。通常GPS設備獲取的經緯度屬於WGS84座標系,這是一個比較通用的座標體系。因爲某些緣由國內不能直接使用WGS84座標,所以百度地圖API的經緯度是通過加密偏移的。git
平面座標
前面說過,球面上的形狀須要通過投影才能變換爲平面上的形狀,變換後就須要有一個平面座標系統來描述地圖上某個位置。百度地圖API默認使用墨卡託投影(Mercator Projection),一樣須要注意的是因爲投影參數不一樣,一樣是墨卡託投影也會有所差異。
平面座標系的原點與經緯度的原點一致,即赤道與0度經線相交的位置:api
在百度地圖API中,平面座標是以最大級別18級爲基準的。就是說在18級下,平面座標的一個單位就表明了屏幕上的1個像素。平面座標與地圖所展現的級別沒有關係,也就是說在1級和18級下,天安門位置的平面座標都是一致的。那麼如何知道某個位置的平面座標呢?可經過BMap.MercatorProjection類來完成,該類提供經緯度與平面座標互相轉換的方法。例如天安門的經緯度大約爲116.404, 39.915,通過轉換便可獲得平面座標:this
var projection = new BMap.MercatorProjection(); var point = projection.lngLatToPoint(new BMap.Point(116.404, 39.915)); alert(point.x + ", " + point.y);
結果以下:
加密
這個就是平面座標。你能夠這樣理解它的含義:第18級下,天安門距離座標原點的位置差爲:12958175, 4825923.77,單位爲像素。3d
像素座標
在第18級下,咱們直接將平面座標向下取整就獲得了像素座標,而在其餘級別下能夠經過以下公式進行換算(這裏取整爲向下取整):code
像素座標 = |平面座標 × Math.pow(2, zoom – 18)|htm
好比通過計算,在第4級天安門位置的像素座標是:790, 294
不一樣級別下,同一個地理位置的像素座標是不同的,它與當前地圖的級別相關。
圖塊座標
百度地圖API在展現地圖時是將整個地圖圖片切割成若干圖塊來顯示的,當地圖初始化或是地圖級別、中心點位置發生變化時,地圖API會根據當前像素座標計算出視野內須要的圖塊座標(也叫圖塊編號),從而加載對應的圖塊用以顯示地圖。
百度地圖的圖塊座標原點與平面座標一致,從原點向右上方開始編號爲0, 0:
如何知道某個位置的圖塊座標呢?經過以下公式計算便可(這裏爲向下取整):
圖塊座標 = |像素座標 ÷ 256|
256其實是每一個圖塊的寬度和高度,咱們用像素座標除以這個數就知道圖塊座標了。還以天安門爲例,在第4級下天安門所在的圖塊編號爲:3, 1,而在第18級下,圖塊編號爲:50617, 18851
可視區域座標
地圖都是顯示在肯定大小的矩形框中的,這個矩形框一般是開發者在初始化地圖傳入的某個容器元素。這個矩形框也有本身的座標系,在百度地圖API中稱之爲可視區域座標系,它的原點位於矩形的左上角。
經過Map類的pointToPixel和pixelToPoint方法能夠相互轉換經緯度座標與可視區域座標。
覆蓋物座標
覆蓋物在實現上就是若干DOM元素,這些元素會被放在若干覆蓋物容器內(具體請參考地圖API開發指南),那麼覆蓋物的座標實際上就是相對於這些覆蓋物容器的座標。在地圖初始化完成後,覆蓋物容器的左上角與地圖可視區域左上角位置相同,一旦地圖被移動、縮放,覆蓋物容器位置就會發生變化。在自定義覆蓋物的時候API提供經緯度信息,而開發者須要自行將經緯度轉換爲覆蓋物的像素座標,從而覆蓋物才能顯示在正確的位置上。這個轉換過程能夠經過Map的pointToOverlayPixel和overlayPixelToPoint兩個方法來實現。
講這麼多都快暈了吧,咱們最後經過一個完整的代碼示例來回顧上面所提到的座標系概念:
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>地圖座標概念</title> <script src="http://api.map.baidu.com/api?v=1.2"></script> </head> <body> <div id="map_container" style="width:500px;height:320px;"></div> <script> var map = new BMap.Map('map_container', {defaultCursor: 'default'}); map.centerAndZoom(new BMap.Point(116.404, 39.915), 11); var TILE_SIZE = 256; map.addEventListener('click', function(e){ var info = new BMap.InfoWindow('', {width: 260}); var projection = this.getMapType().getProjection(); var lngLat = e.point; var lngLatStr = "經緯度:" + lngLat.lng + ", " + lngLat.lat; var worldCoordinate = projection.lngLatToPoint(lngLat); var worldCoordStr = " 平面座標:" + 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 = " 像素座標:" + pixelCoordinate.x + ", " + pixelCoordinate.y; var tileCoordinate = new BMap.Pixel(Math.floor(pixelCoordinate.x / 256), Math.floor(pixelCoordinate.y / 256)); var tileCoordStr = " 圖塊座標:" + tileCoordinate.x + ", " + tileCoordinate.y; var viewportCoordinate = map.pointToPixel(lngLat); var viewportCoordStr = " 可視區域座標:" + viewportCoordinate.x + ", " + viewportCoordinate.y; var overlayCoordinate = map.pointToOverlayPixel(lngLat); var overlayCoordStr = " 覆蓋物座標:" + overlayCoordinate.x + ", " + overlayCoordinate.y; info.setContent(lngLatStr + worldCoordStr + pixelCoordStr + tileCoordStr + viewportCoordStr + overlayCoordStr); map.openInfoWindow(info, lngLat); }); </script> </body> </html>
效果如圖: