平臺地址:http://lbs.amap.com/api/javascript-api/example/amap-ui-districtcluster/custom-cluster-markerjavascript
在作以前得科普一下,百度和高德,谷歌的經緯度是有誤差的。php
瞭解經緯度誤差緣由(pc測試可先不考慮,高德地圖api定位在移動端顯示定位失敗,故採用百度地圖獲取經緯度,而後傳給高德api轉化座標):css
適用場景html
爲了使用高德服務,用戶須要將非高德座標轉換爲高德座標。java
地址:http://lbs.amap.com/api/webservice/guide/api/convert/web
地址:http://www.gpsspg.com/maps.htmajax
2.示例中心:http://lbs.amap.com/api/javascript-api/example/amap-ui-simplemarker/indexapi
<!doctype html> <html lang="zh-CN"> <head> <!-- 原始地址://webapi.amap.com/ui/1.0/ui/geo/DistrictCluster/examples/plus-point-simplifier.html --> <!--<base href="//webapi.amap.com/ui/1.0/ui/geo/DistrictCluster/examples/" />--> <meta charset="utf-8"> <meta name="viewport" content="initial-scale=0.8, user-scalable=yes, width=device-width"> <title>區劃聚合+海量點展現+定位+自定義標記</title> <link rel="stylesheet" href="http://cache.amap.com/lbs/static/main1119.css"/> <!--調整容器大小和一些目標地點樣式大小,一級隱藏,須要使用--> <link rel="stylesheet" href="css/map_common.css"> <!--定位座標的css樣式,帶一些水波效果,能夠不加,在updateMarker生成標記的地方,用img的url連接便可--> <link rel="stylesheet" href="css/ico_position.css"> <!--一些樣式修改和遮罩彈框樣式,能夠不加,默認是顯示的,經過js觸發顯示和關閉--> <link rel="stylesheet" href="css/map_plus.css"> <!--高德自帶,須要使用--> <script type="text/javascript" src='//webapi.amap.com/maps?v=1.4.3&key=d59a0ae0dd2a9b17cbbc480bea2f2033'></script> <!-- UI組件庫 1.0 --> <script src="//webapi.amap.com/ui/1.0/main.js?v=1.0.11"></script> <!--如下爲工具使用,好比公交,和高德自身定位,如下代碼暫不使用--> <!--<script type="text/javascript"--> <!--src="http://webapi.amap.com/maps?v=1.4.3&key=你的高德地圖祕鑰&plugin=AMap.Transfer"></script>--> <!--<script type="text/javascript" src="http://cache.amap.com/lbs/static/addToolbar.js"></script>--> </head> <body id="body"> <div id="container"></div> <script type="text/javascript"> //建立地圖 var map = new AMap.Map('container', { resizeEnable: true, expandZoomRange: true, zoom: 10, zooms: [10, 16], cursor: 'default', center: [122.947398, 34.351598]/*中心肯定暫時用不上*/ }); // 地圖初始化 function initPage(DistrictCluster, PointSimplifier, $) { // 1.具體座標點設置 var pointSimplifierIns = new PointSimplifier({ map: map, //所屬的地圖實例 autoSetFitView: false, //禁止自動更新地圖視野 zIndex: 110, getPosition: function (item) { if (!item) { return null; } var parts = item.split(','); //返回經緯度 return [parseFloat(parts[0]), parseFloat(parts[1]), parts[2]]; }, getHoverTitle: function (dataItem) { var parts1 = dataItem.split(','); return parts1[2]; }, renderOptions: { //點的樣式 pointStyle: { width: 20, height: 20, fillStyle: 'rgba(55, 175, 55, 0.8)', }, // hover層級大小 pointHoverStyle: { width: 20, height: 20, fillStyle: 'rgba(255, 175, 55, 0.8)', }, // 點擊範圍大小 pointHardcoreStyle: { width: 50, height: 50, lineWidth: 3, }, //鼠標hover時的title信息 hoverTitleStyle: { position: 'left', offset: [3, 0], }, } }); // 2.地區塊設置 var distCluster = new DistrictCluster({ zIndex: 102, map: map, //所屬的地圖實例 getPosition: function (item) { if (!item) { return null; } var parts = item.split(','); //返回經緯度 return [parseFloat(parts[0]), parseFloat(parts[1]), parts[2]]; }, renderOptions: { featureStyle: { fillStyle: 'rgba(0, 0, 0, 1)', lineWidth: 1, strokeStyle: 'rgba(55, 175, 55, 0.8)', hoverOptions: { fillStyle: 'rgba(255, 0, 0, 0.2)', lineWidth: 2, strokeStyle: 'rgba(255, 0, 0, 0.8)' } }, //直接定義某寫區劃面的樣式 getFeatureStyle: function(feature, dataItems) { if (dataItems.length > 2) { return { fillStyle: 'rgba(0, 0, 0, 0.6)' }; } else if (dataItems.length > 1) { return { fillStyle: 'rgba(0, 0, 0, 0.6)' }; } return {}; }, featureEventSupport: true, clusterMarkerEventSupport: true, clusterMarkerEventNames: ['click', 'rightclick', 'mouseover', 'mouseout'], //顯示在所轄數據點的平均位置 getClusterMarkerPosition: DistrictCluster.ClusterMarkerPositionStrategy.AVERAGE_POINTS_POSITION, getClusterMarker: function (feature, dataItems, recycledMarker) { //label內容 var name3 = feature.properties.name.length < 4 ? feature.properties.name : (feature.properties.name[0] + feature.properties.name[1]) var content = name3 + '<br />' + dataItems.length + '個'; var label = { offset: new AMap.Pixel(0, 0), //修改label相對於marker的位置 //----------要改等級--------- // content: map.getZoom() > 13 ? content : null content: content }; if (dataItems.length > 0) { //存在可回收利用的marker if (recycledMarker) { //直接更新內容返回 recycledMarker.setLabel(label); return recycledMarker; } //返回一個新的Marker return new AMap.Marker({ //----------要改等級--------- // label: map.getZoom() > 13 ? label : null, label: label, }); } } } }); window.distCluster = distCluster; //根據當前zoom調整點的尺寸,大小 // 3.自定義定位 function selfPosition() { addMarker(); // 實例化點標記 function addMarker() { marker = new AMap.Marker({}); marker.setMap(map); } function updateMarker() { // 自定義點標記內容 var markerContent = document.createElement("div"); // 點標記中的圖標 var ico_position = document.createElement("div"); ico_position.className = 'ico_position'; var pin = document.createElement("div"); pin.className = 'pin'; var pulse = document.createElement("div"); pulse.className = 'pulse'; markerContent.appendChild(ico_position); ico_position.appendChild(pin); ico_position.appendChild(pulse); // 點標記中的文本 var markerSpan = document.createElement("span"); markerSpan.className = 'marker'; markerSpan.innerHTML = "我在這"; markerContent.appendChild(markerSpan); ////如下爲默認圖片展現 //// 點標記中的圖標 //var markerImg = document.createElement("img"); //markerImg.className = "markerlnglat"; //markerImg.src = "http://webapi.amap.com/theme/v1.3/markers/n/mark_r.png"; //markerContent.appendChild(markerImg); //// 點標記中的文本 //var markerSpan = document.createElement("span"); //markerSpan.className = 'marker'; //markerSpan.innerHTML = "Hi,我換新裝備啦!"; //markerContent.appendChild(markerSpan); marker.setContent(markerContent); //更新點標記內容 marker.setPosition([108.992398, 34.256198]); //更新點標記位置,若是是固定的這麼寫下面不用轉化座標了 //百度座標轉化高德座標,使用高德api座標(如下爲php程序調用發送{$xpoint}, {$ypoint}座標點) // htmlobj = $.ajax({ // url: "http://restapi.amap.com/v3/assistant/coordinate/convert?key=c67d73f88613f4f574df092a93602c43&locations={$xpoint},{$ypoint}&coordsys=baidu", // async: false // }); // var obj = JSON.parse(htmlobj.responseText); // var parts1 = obj.locations.split(','); // console.log('精度:',parts1[0],'緯度:',parts1[1]) // marker.setPosition([parts1[0], parts1[1]]); //更新點標記位置 // console.log('x座標:', {$xpoint}, 'y座標:', {$ypoint}); } updateMarker(); } selfPosition(); // 4.刷新顯示 function refresh() { var zoom = map.getZoom(); if (zoom < 13) { $('.amap-marker-label').show()//區縣顯示內容 pointSimplifierIns.hide();//具體座標點顯示 } else if (zoom > 16) { map.setZoom(12); } else { $('.amap-marker-label').hide();//區縣顯示內容 pointSimplifierIns.show();//具體座標點顯示 } } // 5.監聽事件 map.on('zoomend', function () { refresh(); console.log('zoom1', map.getZoom()) }); pointSimplifierIns.on('pointClick', function (e, record) { var parts1 = record.data.split(','); $('#showMsg').html(parts1[2]); $('.mask').show(500) // $('.mask').fadeIn(500)/*注意:漸顯的效果只能pc顯示,移動端不反應*/ }); distCluster.on('featureClick', function (e, feature) { if (map.getZoom() == 16) { map.setZoom(16); } else { map.setZoom(map.getZoom() + 1); } // 設置點擊點爲視圖座標 map.setCenter([e.originalEvent.lnglat.getLng(), e.originalEvent.lnglat.getLat()]) console.log(e, feature.properties.name) }); distCluster.on('clusterMarkerClick clusterMarkerRightclick', function (e, record) { if (map.getZoom() == 16) { map.setZoom(16); } else { map.setZoom(map.getZoom() + 1); } map.setCenter([e.originalEvent.lnglat.getLng(), e.originalEvent.lnglat.getLat()]) console.log(e, record.feature.properties.name) }); $('.mask').on('click', function () { $('.mask').hide(500); // $('.mask').fadeOut(500);/*注意:漸隱的效果只能pc顯示,移動端不反應*/ }); $('#showMsg').on('click', function (e) { // 阻止事件冒泡 e.stopPropagation() }); $('<div id="loadingTip">加載數據,請稍候...</div>').appendTo(document.body); $.get('http://localhost:63342/map/10w1.txt', function (csv) { // 本地同級目錄的數據文件,除官方數據已有的經緯度以外,添加了第三個自定義信息 $('#loadingTip').remove(); var data = csv.split('\n'); distCluster.setData(data); pointSimplifierIns.setData(data); }); } //加載相關組件 AMapUI.load(['ui/geo/DistrictCluster', 'ui/misc/PointSimplifier', 'lib/$'], function (DistrictCluster, PointSimplifier, $) { // 建立點擊具體座標點後彈框樣式 function creatMask() { var bodyin = document.getElementById('body'); var new_obj1 = document.createElement("div"); new_obj1.setAttribute("class", "mask"); var new_obj2 = document.createElement("div"); new_obj2.setAttribute("id", "showMsg"); bodyin.appendChild(new_obj1); new_obj1.appendChild(new_obj2); } creatMask(); $('.mask').hide(); //啓動頁面 initPage(DistrictCluster, PointSimplifier, $); }); </script> </body> </html>
108.935398,34.256598,西安市1 108.926398,34.316598,西安市2 108.947398,34.351598,西安市3 108.868398,34.253598,西安市4 108.879398,34.246598,西安市5 108.981398,34.354598,西安市6 108.992398,34.256198,西安市7
html, body, #container { width: 100%; height: 100%; margin: 0px; } #loadingTip { position: absolute; z-index: 9999; top: 50%; left: -50%; padding: 3px 3px; background: red; color: #fff; font-size: 14px; border: none; } .amap-marker-label { text-align: center; padding:1rem; width: 42px; height: 42px; background: rgba(55, 175, 55, 0.8); color: #fff; border-radius: 50%; line-height:1.5rem; border: 1px solid #fff; font-size: 1rem; } .amap-icon { width: 42px !important; top: 0; display: none; } .amap-icon img { width: 42px !important; height: 42px !important; left: 0 !important; visibility: hidden; cursor: pointer; } .amap-toolbar { display: none }
展現效果如上圖瀏覽器
1.高德地圖示例也有聚合顯示個數的,可是爲網格聚合,按照面積計算,不適合用其爲基礎模板,應當選用帶有海量展現點和的行政區域聚合安全
2.因爲電腦和移動端屏幕可視區域不一樣,由縮放邏輯控制的顯示狀況可能會出現差別,能夠經過meta標籤裏的
initial-scale=0.8
這個來修改
3.注意提供數據格式的拆分
var data = csv.split('\n');
data.split(',');
4.本示例經過隱藏樣例的定位圖標,將定位點的樣式放大而寫,你也能夠經過從新書寫標籤樣式來改變
如下爲主要研究示例:
map_demo2.html
<!doctype html> <html lang="zh-CN"> <head> <!-- 原始地址://webapi.amap.com/ui/1.0/ui/geo/DistrictCluster/examples/plus-point-simplifier.html --> <!--<base href="//webapi.amap.com/ui/1.0/ui/geo/DistrictCluster/examples/" />--> <meta charset="utf-8"> <meta name="viewport" content="initial-scale=1.0, user-scalable=yes, width=device-width"> <title>區劃聚合+海量點展現+定位+最近公交路線</title> <!--調整容器大小和一些目標地點樣式大小,一級隱藏,須要使用--> <link rel="stylesheet" href="css/map_common.css"> <!--一些樣式修改和遮罩彈框樣式,能夠不加,須要使用--> <link rel="stylesheet" href="css/map_plus.css"> <link rel="stylesheet" href="http://cache.amap.com/lbs/static/main1119.css"/> <script type="text/javascript" src='//webapi.amap.com/maps?v=1.4.3&key=d59a0ae0dd2a9b17cbbc480bea2f2033'></script> <!-- UI組件庫 1.0 --> <script src="//webapi.amap.com/ui/1.0/main.js?v=1.0.11"></script> <script type="text/javascript" src="http://webapi.amap.com/maps?v=1.4.3&key=你的高德地圖祕鑰&plugin=AMap.Transfer"></script> <script type="text/javascript" src="http://cache.amap.com/lbs/static/addToolbar.js"></script> </head> <body> <div id="container"></div> <div id="panel"></div> <div id="tip"></div> <div id="btn_minRoad" class="btn_road">點擊查看最近公交路線</div> <script type="text/javascript"> //建立地圖 var map = new AMap.Map('container', { resizeEnable: true, expandZoomRange: true, zoom: 10, zooms: [10, 15], cursor: 'default', center:[112.947398,34.351598] }); // 地圖初始化 function initPage(DistrictCluster, PointSimplifier, $) { var pointSimplifierIns = new PointSimplifier({ map: map, //所屬的地圖實例 autoSetFitView: false, //禁止自動更新地圖視野 zIndex: 110, getPosition: function (item) { if (!item) { return null; } var parts = item.split(','); //返回經緯度 return [parseFloat(parts[0]), parseFloat(parts[1]), parts[2]]; }, getHoverTitle: function (dataItem) { var parts1 = dataItem.split(','); return parts1[2]; }, renderOptions: { //點的樣式 pointStyle: { width: 20, height: 20, fillStyle: 'rgba(255, 0, 0, 1)', }, // hover層級大小 pointHoverStyle: { width: 20, height: 20, }, // 點擊範圍大小 pointHardcoreStyle: { width: 20, height: 20, lineWidth: 3, }, //鼠標hover時的title信息 hoverTitleStyle: { position: 'left', offset: [3, 0], }, } }); var distCluster = new DistrictCluster({ zIndex: 102, map: map, //所屬的地圖實例 getPosition: function (item) { if (!item) { return null; } var parts = item.split(','); //返回經緯度 return [parseFloat(parts[0]), parseFloat(parts[1]), parts[2]]; }, renderOptions: { //顯示在所轄數據點的平均位置 getClusterMarkerPosition: DistrictCluster.ClusterMarkerPositionStrategy.AVERAGE_POINTS_POSITION, getClusterMarker: function (feature, dataItems, recycledMarker) { //label內容 var name3 = feature.properties.name.length < 4 ? feature.properties.name : (feature.properties.name[0] + feature.properties.name[1]) var content = name3 + '<br />' + dataItems.length+'個'; var label = { offset: new AMap.Pixel(-20, 0), //修改label相對於marker的位置 //----------要改等級--------- // content: map.getZoom() < 13 ? content : null content: content }; if (dataItems.length > 0) { //存在可回收利用的marker if (recycledMarker) { //直接更新內容返回 recycledMarker.setLabel(label); return recycledMarker; } //返回一個新的Marker return new AMap.Marker({ //----------要改等級--------- // label: map.getZoom() < 13 ? label : null, label: label, }); } } } }); window.distCluster = distCluster; //根據當前zoom調整點的尺寸,大小 var pointStyle = pointSimplifierIns.getRenderOptions().pointStyle; pointStyle.width = pointStyle.height = 8 * Math.pow(1.2, map.getZoom() - 3); function refresh() { var zoom = map.getZoom(); if (zoom == 10) { $('.amap-marker-label').show()//區縣顯示內容 pointSimplifierIns.hide();//具體座標點顯示 } else if (zoom == 11) { map.setZoom(12); } else if (zoom == 12) { map.setZoom(12); $('.amap-marker-label').hide();//區縣顯示內容 pointSimplifierIns.show();//具體座標點顯示 } else if (zoom == 13) { map.setZoom(13); $('.amap-marker-label').hide();//區縣顯示內容 pointSimplifierIns.show();//具體座標點顯示 }else if (zoom == 14) { map.setZoom(14); $('.amap-marker-label').hide();//區縣顯示內容 pointSimplifierIns.show();//具體座標點顯示 }else { map.setZoom(10); } } //監聽事件 map.on('zoomend', function () { refresh(); console.log('zoom1', map.getZoom()) }); map.on('click', function (e) { map.setZoom(map.getZoom() + 1); map.setCenter([e.lnglat.getLng(), e.lnglat.getLat()]) refresh(); // alert('您在[ ' + e.lnglat.getLng() + ',' + e.lnglat.getLat() + ' ]的位置點擊了地圖!'); }); pointSimplifierIns.on('pointClick', function (e, record) { var parts1 = record.data.split(','); map.setZoom(10); alert(parts1[2]) }); //------------------公交路線規劃---------------------- function road_planning(data_Geolocation) { btn_minRoad.onclick = function () { var transOptions = { map: map, city: '西安市', panel: 'panel', //cityd:'烏魯木齊', policy: AMap.TransferPolicy.LEAST_TIME }; //構造公交換乘類 var transfer = new AMap.Transfer(transOptions); //根據起、終點座標查詢公交換乘路線 var min_road = Number.POSITIVE_INFINITY; var min_roads = []; var postion_now_j = data_Geolocation.position.getLng(); var postion_now_w = data_Geolocation.position.getLat(); function minRoad(data_Geolocation) { for (var i = 0; i < pointSimplifierIns._data.source.length; i++) { // console.log(pointSimplifierIns._data.source[i]) if (!pointSimplifierIns._data.source[i]) { return null; } var parts = pointSimplifierIns._data.source[i].split(','); postion_target_j = parseFloat(parts[0]); postion_target_w = parseFloat(parts[1]); Math.pow(postion_target_j - postion_now_j, 2); Math.pow(postion_now_w - postion_target_w, 2); if ((Math.pow(postion_target_j - postion_now_j, 2) + Math.pow(postion_now_w - postion_target_w, 2)) < min_road) { min_road = Math.pow(postion_target_j - postion_now_j, 2) + Math.pow(postion_now_w - postion_target_w, 2) min_roads = [postion_target_j, postion_target_w]; console.log('min_roads', min_roads[0], min_roads[1]) console.log('min_road', (Math.pow(postion_target_j - postion_now_j, 2) + Math.pow(postion_now_w - postion_target_w, 2))) } //返回經緯度 return min_roads } }; transfer.search(new AMap.LngLat(postion_now_j, postion_now_w), new AMap.LngLat(minRoad()[0], minRoad()[1])); } } //------------------定位功能---------------------- var geolocation; //加載地圖,調用瀏覽器定位服務 map.plugin('AMap.Geolocation', function () { geolocation = new AMap.Geolocation({ enableHighAccuracy: true,//是否使用高精度定位,默認:true timeout: 10000, //超過10秒後中止定位,默認:無窮大 buttonOffset: new AMap.Pixel(10, 20),//定位按鈕與設置的停靠位置的偏移量,默認:Pixel(10, 20) zoomToAccuracy: true, //定位成功後調整地圖視野範圍使定位位置及精度範圍視野內可見,默認:false buttonPosition: 'RB', }); map.addControl(geolocation); geolocation.getCurrentPosition(); AMap.event.addListener(geolocation, 'complete', complete_zoom);//返回定位信息 AMap.event.addListener(geolocation, 'error', onError); //返回定位出錯信息 }); var zoom2 = map.getZoom(); console.log('zoom2:',zoom2); //解析定位結果 function complete_zoom(data_Geolocation) { var zoom = map.getZoom(); console.log('zoom3:',zoom); map.setZoom(zoom); // var str = ['定位成功']; // str.push('經度:' + data_Geolocation.position.getLng()); // str.push('緯度:' + data_Geolocation.position.getLat()); // if (data_Geolocation.accuracy) { // str.push('精度:' + data_Geolocation.accuracy + ' 米'); // }//如爲IP精肯定位結果則沒有精度信息 // str.push('是否通過偏移:' + (data_Geolocation.isConverted ? '是' : '否')); // document.getElementById('tip').innerHTML = str.join('<br>'); var btn_minRoad = $('#btn_minRoad'); road_planning(data_Geolocation) } //解析定位錯誤信息 function onError(data_Geolocation) { document.getElementById('tip').innerHTML = '定位失敗'; } //------------打開設備判斷---------------- if (/Android|webOS|iPhone|iPod|BlackBerry/i.test(navigator.userAgent)) { $('#panel').css('display', 'none'); $('.amap-toolbar').hide(); } else { $('#panel').css('display', 'block') } $('<div id="loadingTip">加載數據,請稍候...</div>').appendTo(document.body); $.get('http://localhost:63342/map/10w1.txt', function (csv) { // 本地同級目錄的數據文件,除官方數據已有的經緯度以外,添加了第三個自定義信息 $('#loadingTip').remove(); var data = csv.split('\n'); distCluster.setData(data); pointSimplifierIns.setData(data); }); } //加載相關組件 AMapUI.load(['ui/geo/DistrictCluster', 'ui/misc/PointSimplifier', 'lib/$'], function (DistrictCluster, PointSimplifier, $) { //啓動頁面 initPage(DistrictCluster, PointSimplifier, $); }); </script> </body> </html>
css,txt文件同,可本地環境打開顯示
1.高德地圖定位失敗的緣由
在高德地圖-瀏覽器定位的官方文檔上有這樣的一句註釋「/***************************************
因爲Chrome、IOS10等已再也不支持非安全域的瀏覽器定位請求,爲保證定位成功率和精度,請儘快升級您的站點到HTTPS。
***************************************/」,不知道是否是和定位失敗有關
另外,發現瀏覽器定位的時候,會有彈框提示問是否容許,只有點擊肯定才能定位,但有的瀏覽器沒有提示彈框,或者用戶第一次點擊取消,以後怎麼刷新都沒有彈框確認定位,定位也就失敗了。js中如何寫定位提醒的彈框呢?