百度地圖API詳解之地圖座標系統

在百度地圖API中,你須要瞭解以下座標系:javascript

經緯度:經過經度(longitude)和緯度(latitude)描述的地球上的某個位置。
平面座標:投影以後的座標(用x和y描述),用於在平面上標識某個位置。
像素座標:描述不一樣級別下地圖上某點的位置。
圖塊座標:地圖圖塊編號(用x和y描述)。
可視區域座標:地圖可視區域的座標系(用x和y描述)。
覆蓋物座標:覆蓋物相對於容器的座標(用x和y描述)。html

別被這麼多的座標系嚇着,看完了後面的講解相信你會逐漸理解它們。java

經緯度
這個就很少說了,不熟悉的能夠翻翻地理書。但須要注意的是即使同是經緯度座標也可能屬於不一樣的座標體系。通常GPS設備獲取的經緯度屬於WGS84座標系,這是一個比較通用的座標體系。因爲某些緣由國內不能直接使用WGS84座標,所以百度地圖API的經緯度是通過加密偏移的。git

平面座標
前面說過,球面上的形狀須要通過投影才能變換爲平面上的形狀,變換後就須要有一個平面座標系統來描述地圖上某個位置。百度地圖API默認使用墨卡託投影(Mercator Projection),一樣須要注意的是因爲投影參數不一樣,一樣是墨卡託投影也會有所差異。
平面座標系的原點與經緯度的原點一致,即赤道與0度經線相交的位置:api

0f9f47ec256410b02e2e2112

在百度地圖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);

結果以下:
07c0c4197b9d101bdbb4bd1d加密

這個就是平面座標。你能夠這樣理解它的含義:第18級下,天安門距離座標原點的位置差爲:12958175, 4825923.77,單位爲像素。3d

像素座標
在第18級下,咱們直接將平面座標向下取整就獲得了像素座標,而在其餘級別下能夠經過以下公式進行換算(這裏取整爲向下取整):code

像素座標 = |平面座標 × Math.pow(2, zoom – 18)|htm

好比通過計算,在第4級天安門位置的像素座標是:790, 294
25c9ed092446bae3d0581bef
不一樣級別下,同一個地理位置的像素座標是不同的,它與當前地圖的級別相關。

圖塊座標
百度地圖API在展現地圖時是將整個地圖圖片切割成若干圖塊來顯示的,當地圖初始化或是地圖級別、中心點位置發生變化時,地圖API會根據當前像素座標計算出視野內須要的圖塊座標(也叫圖塊編號),從而加載對應的圖塊用以顯示地圖。
百度地圖的圖塊座標原點與平面座標一致,從原點向右上方開始編號爲0, 0:
833962df022ded72485403eb
如何知道某個位置的圖塊座標呢?經過以下公式計算便可(這裏爲向下取整):

圖塊座標 = |像素座標 ÷ 256|

256其實是每一個圖塊的寬度和高度,咱們用像素座標除以這個數就知道圖塊座標了。還以天安門爲例,在第4級下天安門所在的圖塊編號爲:3, 1,而在第18級下,圖塊編號爲:50617, 18851

可視區域座標
地圖都是顯示在肯定大小的矩形框中的,這個矩形框一般是開發者在初始化地圖傳入的某個容器元素。這個矩形框也有本身的座標系,在百度地圖API中稱之爲可視區域座標系,它的原點位於矩形的左上角。
7eac4ccf8a67b95cf9dc61f7
經過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>

效果如圖:
830a3f3b1c10ef8b14cecbfc

相關文章
相關標籤/搜索