【百度地圖API】如何自定義地圖圖層?實例:制作麻點圖(自定義圖層+熱區)


摘要:自定義地圖圖層的用途十分廣泛。常見的應用,比如制作魔獸地圖和清華校園地圖(使用切圖工具即可輕松實現)。今天我們來學習,當地圖上有大量標注,比如600萬個的時候,我們如何用“麻點圖”來實現標注的展示。

----------------------------------------------------------------------------------------------------------

“麻點圖”展示圖,如下圖所示:

 

 

“麻點圖”實現原理

1、將麻點做在同一張圖片上,然后利用自定義圖層接口,將麻點圖貼在地圖底圖上;

2、然后利用熱區接口,使鼠標放在熱點上,有文字顯示。

3、可以自己加上信息窗口等覆蓋物,讓熱區hotspot看起來像標注marker一樣。

 

 

根據地圖級別確定圖塊總面積

一個圖塊是256*256的圖片構成的。

當地圖為1級時,整個地圖由4張圖片構成,如下圖(中心點為0,0):

 

所以圖層的長寬為512*512。如下圖:

 

將此圖裁成4塊,貼到地圖底圖上。

 

 

 

同理,其他地圖級別、圖塊數量和圖塊總面積的關系如下表:

地圖級別    圖塊數量            圖塊總面積        備注

1             2*2=4              512*512          2^1=2, 2^2=4, 256*2=512

2             4*4=16            1024*1024      2^2=4, 4^2=16, 256*4=1024

3             8*8=64            4096*4096      2^3=8, 8^2=64, 256*8=2046

4             16*16=256       ……

zoom       (2^zoom)^2      (256*(zoom^2))^2

 

 

以zoom=3為例,制作熱區

使用自定義圖層的方法,將麻點圖貼到地圖上。

var tileLayer = new BMap.TileLayer({isTransparentPng: true});
tileLayer.getTilesUrl = function(tileCoord, zoom) {
var x = tileCoord.x;
var y = tileCoord.y;
return 'tiles/' + zoom + '/tile' + x + '_' + y + '.png';
}

 

然后為每一個麻點添加一個熱區。(示例中只添加了可視區域內的21個麻點)

//創建熱區
var p1 = new BMap.Point(-53.278572,36.83958);
var h1 = new BMap.Hotspot(p1, {text: "第1個點"});
map.addHotspot(h1);

 

最終效果圖:(用此方法,可以添加600萬個以上的熱區哦~)



 

 

 

 

全部源代碼:

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>熱區+自定義圖層</title>
<script type="text/javascript" src="http://api.map.baidu.com/api?v=1.2"></script>
</head>
<body>
<div id="map" style="width:400px;height:300px"></div>
<div id="info" style="width:400px;height:800px"></div>
<script type="text/javascript">
var tileLayer = new BMap.TileLayer({isTransparentPng: true});
tileLayer.getTilesUrl
= function(tileCoord, zoom) {
var x = tileCoord.x;
var y = tileCoord.y;
return 'tiles/' + zoom + '/tile' + x + '_' + y + '.png';
}
var map = new BMap.Map('map');
map.addTileLayer(tileLayer);
//map.addControl(new BMap.NavigationControl());
map.centerAndZoom(new BMap.Point(0, 0), 3);

//點擊獲取屏幕經緯度
map.addEventListener("click",function(e){
document.getElementById(
"info").innerHTML += e.point.lng + "," + e.point.lat + "</br>";
});

//創建熱區
var p1 = new BMap.Point(-53.278572,36.83958);
var h1 = new BMap.Hotspot(p1, {text: "第1個點"});
map.addHotspot(h1);

var p2 = new BMap.Point(-14.717837,35.647352);
var h2 = new BMap.Hotspot(p2, {text: "第2個點"});
map.addHotspot(h2);

var p3 = new BMap.Point(9.713773,36.126444);
var h3 = new BMap.Hotspot(p3, {text: "第3個點"});
map.addHotspot(h3);

var p4 = new BMap.Point(43.564799,30.699049);
var h4 = new BMap.Hotspot(p4, {text: "第4個點"});
map.addHotspot(h4);

var p5 = new BMap.Point(30.024388,29.418746);
var h5 = new BMap.Hotspot(p5, {text: "第5個點"});
map.addHotspot(h5);

var p6 = new BMap.Point(29.141318,18.90614);
var h6 = new BMap.Hotspot(p6, {text: "第6個點"});
map.addHotspot(h6);

var p7 = new BMap.Point(37.677664,17.781705);
var h7 = new BMap.Hotspot(p7, {text: "第7個點"});
map.addHotspot(h7);

var p8 = new BMap.Point(21.488043,10.607121);
var h8 = new BMap.Hotspot(p8, {text: "第8個點"});
map.addHotspot(h8);

var p9 = new BMap.Point(16.189621,15.225979);
var h9 = new BMap.Hotspot(p9, {text: "第9個點"});
map.addHotspot(h9);

var p10 = new BMap.Point(11.77427,14.939957);
var h10 = new BMap.Hotspot(p10, {text: "第10個點"});
map.addHotspot(h10);

var p11 = new BMap.Point(11.77427,20.855394);
var h11 = new BMap.Hotspot(p11, {text: "第11個點"});
map.addHotspot(h11);

var p12 = new BMap.Point(-10.596843,8.562041);
var h12 = new BMap.Hotspot(p12, {text: "第12個點"});
map.addHotspot(h12);

var p13 = new BMap.Point(-27.669534,21.131844);
var h13 = new BMap.Hotspot(p1, {text: "第13個點"});
map.addHotspot(h13);

var p14 = new BMap.Point(-36.20588,23.866825);
var h14 = new BMap.Hotspot(p14, {text: "第14個點"});
map.addHotspot(h14);

var p15 = new BMap.Point(-15.600908,-23.866825);
var h15 = new BMap.Hotspot(p15, {text: "第15個點"});
map.addHotspot(h15);

var p16 = new BMap.Point(-4.709708,-10.024106);
var h16 = new BMap.Hotspot(p16, {text: "第16個點"});
map.addHotspot(h16);

var p17 = new BMap.Point(19.427545,-4.145408);
var h17 = new BMap.Hotspot(p17, {text: "第17個點"});
map.addHotspot(h17);

var p18 = new BMap.Point(47.09708,-13.50419);
var h18 = new BMap.Hotspot(p18, {text: "第18個點"});
map.addHotspot(h18);

var p19 = new BMap.Point(55.633426,-8.854941);
var h19 = new BMap.Hotspot(p19, {text: "第19個點"});
map.addHotspot(h19);

var p20 = new BMap.Point(-57.105209,2.370216);
var h20 = new BMap.Hotspot(p20, {text: "第20個點"});
map.addHotspot(h20);

var p21 = new BMap.Point(-48.274507,-4.736327);
var h21 = new BMap.Hotspot(p21, {text: "第21個點"});
map.addHotspot(h21);

var p22 = new BMap.Point(-56.222139,-30.699049);
var h22 = new BMap.Hotspot(p22, {text: "第22個點"});
map.addHotspot(h22);
</script>
</body>
</html>



 

 

附錄:

獲取地圖上的經緯度

可以使用以下代碼獲取地圖上任意點的經緯度。

//點擊獲取屏幕經緯度
map.addEventListener("click",function(e){
document.getElementById("info").innerHTML += e.point.lng + "," + e.point.lat + "</br>";
});

 

 

 

大量標注會使地圖變慢,如何解決?

標注數據量請控制在150個以內,以保持各個瀏覽器都能高性能地展示地圖;標注數量在260以內,可以使用自定義覆蓋物實現;標注數量大於300個,建議嘗試marker聚合,或者數據抽希,或者熱區。

Marker聚合:http://tieba.baidu.com/f?kz=1031097376 
數據抽希:比如有10個marker,選擇其中6個做為顯示點。
熱區:如本例。

建議不要一次在地圖上添加過多的marker,而是先把point存儲在數據庫里,當需要顯示某個marker是,再addOverlay。如《顯示可視區域內的標注》;http://www.cnblogs.com/milkmap/archive/2012/02/02/2335989.html

 

 

-----------------------------------------------------------------------------------------

關於屏幕像素,圖塊圖號,經緯度之間的轉換,請查看此篇文章《百度地圖API詳解之地圖坐標系統》http://www.cnblogs.com/jz1108/archive/2011/07/02/2095376.html

 

涉及到以下坐標系:

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

 

計算方式:

  var lngLat = e.point;  
  var lngLatStr = "經緯度:" + lngLat.lng + ", " + lngLat.lat;
  
  var worldCoordinate = projection.lngLatToPoint(lngLat);
  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 = map.pointToPixel(lngLat);
  var viewportCoordStr = "<br />可視區域坐標:" + viewportCoordinate.x + ", " + viewportCoordinate.y;
  
  var overlayCoordinate = map.pointToOverlayPixel(lngLat);
  var overlayCoordStr = "<br />覆蓋物坐標:" + overlayCoordinate.x + ", " + overlayCoordinate.y;

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM