话不多说,先上图:
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});//分三级主要是针对不同级别显示不同的标签,这里可根据自己系统要求自行定制contentif(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;});
}