話不多說,先上圖:
1.點擊省份顯示市級信息標記,點擊市顯示區縣信息標記
2.縮放到市級級別時顯示市級信息標記,縮放到區縣級別時顯示區縣信息標記
(PS:此技術也可以用來開發仿滴滴打車軟件裏的顯示附近車輛位置等功能的開發)
技術選取
地圖插件選擇騰訊地圖(公司方面的原因),標記選擇騰訊地圖自帶的覆蓋物標記(騰訊自帶的點聚合可以實現聚合顯示數量,但功能不適合此功能開發)
技術實現
初始化
初始進入門店區域分佈頁面,初始化地圖,縮放zoom=5(省級),js從後臺抓取所有以省份爲整體的門店數量數據,然後把標記(帶上門店數量)渲染到地圖的相關省上,並初始化map.zoom_changed這個監聽事件(此方法監聽地圖縮放級數變化),初始化標記mark的clickable_changed事件(此方法監聽標記被點擊的事件)
1.縮放地圖事件監聽
1. 當zoom∈(5,8),地圖標記不變化。
2. 當zoom = 8 時,清除所有省份標記,js調用map. getCenter()來獲取地圖中心座標,在通過javascript地址解析逆向獲取中心地址省份名稱,js從後臺拿到該省的以市級爲整體的門店數量數據,然後把標記(帶上門店數量)渲染到地圖的相關市上。
3. 當zoom∈(8,11),地圖標記不變化。
4. 當zoom = 11 時,清除所有市級標記,js調用map. getCenter()來獲取地圖中心座標,在通過javascript地址解析逆向獲取中心地址市級名稱,js從後臺拿到該市的所有區縣門店座標信息,創建位置標記對象,然後把標記渲染到地圖上。
5. 當zoom∈(11,18),地圖標記不變化。
2.點擊標記事件監聽
1. 當省份標記被點擊時,清除所有省份標記,js從後臺拿到該省的以市級爲整體的門店數量數據,創建位置標記對象,然後把標記(帶上門店數量)渲染到地圖的相關市上,zoom調整到8。
2. 當市級標記被點擊時,清除所有市級標記,js從後臺拿到該市的所有區縣門店座標信息,創建位置標記對象,然後把標記渲染到地圖上,zoom調整到11。
代碼實現
一、JS引入
1. 引入騰訊地圖API JS
<script charset="utf-8" src="http://map.qq.com/api/js?v=2.exp&key=your key"></script>
2. 引入loading加載JS
<script charset="utf-8" src="jquery.mloading.js"></script>
二、功能方法
1. 初始化方法
//進入頁面初始化地圖
function init(){
let current_zoom = 5;
let map = initMap(current_zoom);
renderMarkersAndLabels(map,1,data,bindEventLevelOneMarkers);
}
2. 初始化地圖
/**
* 初始化地圖
* @param zoom 縮放級別,默認爲5
* @param latLng 座標對象
*/
function initMap(zoom,latLng){
//以北京爲中心
let center = new qq.maps.LatLng(39.916527,116.397128);
if(!zoom){
zoom = 5
}
if(latLng){
center = latLng
}
//初始化地圖
let map = new qq.maps.Map(document.getElementById("container"), {
// 地圖的中心地理座標。
center: center,
zoom: zoom
});
map.panTo(center);
bindZoomSwithListener(map);
//顯示loading組件
$("#container").mLoading("show");
current_zoom = zoom;
return map;
}
3. 渲染標記和標籤方法
/**
* 渲染標記和標籤
* @param map map地圖對象
* @param level 地圖級別 1:省級 2:市級 3:區縣級
* @param data json數據
* @param markerClickCallback 標記點擊事件方法回調函數
*/
function renderMarkersAndLabels(map,level,data,markerClickCallback){
for(let i = 0 ; i < data.length ; i++ ){
let d = data[i];
if(d.position){
let x = d.position.split(",")[0];
let y = d.position.split(",")[1];
let marker = new qq.maps.Marker({
position: new qq.maps.LatLng(parseFloat(x),parseFloat(y)),
animation:qq.maps.MarkerAnimation.DROP,
map: map
});
//分三級主要是針對不同級別顯示不同的標籤,這裏可根據自己系統要求自行定製content
if(level == 1){
let label = new qq.maps.Label({
position: new qq.maps.LatLng(parseFloat(x),parseFloat(y)),
map: map,
content:d.provinceName + ":" + d.shopNum
});
}
else if(level == 2){
let label = new qq.maps.Label({
position: new qq.maps.LatLng(parseFloat(x),parseFloat(y)),
map: map,
content:d.cityName + ":" + d.shopNum
});
}
else if(level == 3){
let label = new qq.maps.Label({
position: new qq.maps.LatLng(parseFloat(x),parseFloat(y)),
map: map,
content:"門店名稱:" + d.shopName +"<br>門店地址:" + d.shopAddress + "<br>門店電話:" + d.shopTelephone
});
}
//初始化標記點擊事件
if(markerClickCallback){
markerClickCallback(marker);
}
}
}
$("#container").mLoading("hide");
}
4. 逆向解析座標方法
/**
* 逆向解析座標方法
* @param map map地圖對象
* @param level 地圖級別 1:省級 2:市級 3:區縣級
*/
function converseAnalysis(map,level) {
if(level == 2){
let geocoder = new qq.maps.Geocoder({
complete : function(result){
//獲得省份,縮放到市級
let province = result.detail.addressComponents.province;
params.province = province;
permissionService.getCityList(params).then((data)=>{
renderMarkersAndLabels(map,2,data,bindEventLevelTwoMarkers);
});
}
});
geocoder.getAddress(map.center);
}
else if(level == 3){
let geocoder = new qq.maps.Geocoder({
complete : function(result){
//獲得城市,縮放到區縣級
let city = result.detail.addressComponents.city;
params.city = city;
permissionService.getDistrictList(params).then((data)=>{
renderMarkersAndLabels(map,3,data);
});
}
});
geocoder.getAddress(map.center);
}
}
5. 初始化地圖時獲取所有省份門店信息方法
function getProvincesData(map){
permissionService.getList(params).then((data)=>{
renderMarkersAndLabels(map,1,data,bindEventLevelOneMarkers);
});
}
6. 設置省級和市級標記點擊事件方法
/**
* 設置市級標記點擊事件
* @param marker 標記對象
*/
function bindEventLevelTwoMarkers(marker) {
qq.maps.event.addListener(marker, 'click', function() {
let _this = $(this);
let center = new qq.maps.LatLng(_this[0].position.lat, _this[0].position.lng);
//顯示loading組件
$("#container").mLoading("show");
//逆向地址解析
let geocoder = new qq.maps.Geocoder({
complete : function(result){
//獲得城市
let city = result.detail.addressComponents.city;
params.city = city;
permissionService.getDistrictList(params).then((DistrictData)=>{
//創建地圖中心座標
let newMap = initMap(11,center);
current_zoom = 11;
renderMarkersAndLabels(newMap,3,DistrictData,null);
});
}
});
geocoder.getAddress(center);
});
}
/**
* 設置省級標記點擊事件
* @param marker 標記對象
*/
function bindEventLevelOneMarkers(marker) {
qq.maps.event.addListener(marker, 'click', function() {
let _this = $(this);
let center = new qq.maps.LatLng(_this[0].position.lat, _this[0].position.lng);
//顯示loading組件
$("#container").mLoading("show");
//逆向地址解析
let geocoder = new qq.maps.Geocoder({
complete : function(result){
//獲得省份
let province = result.detail.addressComponents.province;
params.province = province;
permissionService.getCityList(params).then((cityData)=>{
let newMap = initMap(8,center);
current_zoom = 8;
renderMarkersAndLabels(newMap,2,cityData,bindEventLevelTwoMarkers);
});
}
});
geocoder.getAddress(center);
});
}
7. 設置省級和市級標記點擊事件方法
/**
* zoom切換監聽事件
* @param map map地圖對象
*/
function bindZoomSwithListener(map) {
qq.maps.event.addListener(map, 'zoom_changed', (tempMap) => {
//從一級跳二級
if(tempMap.target.zoom == 8 && current_zoom == 7 ){
let newMap = initMap(8,tempMap.target.center);
converseAnalysis(newMap,2);
}
//從二級跳三級
else if(tempMap.target.zoom == 11 && current_zoom == 10){
let newMap = initMap(11,tempMap.target.center);
converseAnalysis(newMap,3);
}
//從三級跳二級
else if(tempMap.target.zoom == 8 && current_zoom == 9){
let newMap = initMap(8,tempMap.target.center);
converseAnalysis(newMap,2);
}
//從二級跳一級
else if(tempMap.target.zoom == 5 && current_zoom == 6){
let newMap = initMap(5,tempMap.target.center);
getProvincesData(newMap);
}
current_zoom = tempMap.target.zoom;
});
}