当前位置: 代码网 > it编程>前端脚本>Vue.js > Vue2实现高德地图自定义索引聚合+海量点展示

Vue2实现高德地图自定义索引聚合+海量点展示

2024年07月28日 Vue.js 我要评论
2.样式效果有些不好看,初始版暂定这个,其他样式效果在此版本上更新。1.记录开发过程中遇到的问题,多研究开发手册。

需求分析

目前项目中预实现以下功能:

  1. 分级(省、市、区、海量点)显示点位数据,区县及以上显示聚合信息,包括聚合信息名(省、市、区)和点位数量
  2. 海量点层级下根据设备状态显示不同颜色图标。
  3. 聚合点可点击,省市聚合点点击显示下一级聚合情况,区级聚合点点击后显示区县范围。

功能实现

  1. 搭建地图,初始化省市区数据及点位数据(由后端接口获取,代码省略)。
<template>
    <div id="amapcontainer" class="map-container"> 
    </div>
</template>
<script>
import amaploader from '@amap/amap-jsapi-loader';
window._amapsecurityconfig = {
 	securityjscode: '「申请的安全密钥」',
}
export default {
    name: "amap",
    data: function() {
        return {
            points:[],
            areadata:[],
            clusterindexset:{
                province:{
                    minzoom: 2,
                    maxzoom: 5,
                },
                city: {
                    minzoom: 5,
                    maxzoom: 10,
                },
                district: {
                    minzoom: 10,
                    maxzoom: 12,
                },                                
            },
            polygon:null,
            pointstyles:[
            	{
                    url: require('../../assets/online.png') , 
                    anchor: [25, 50],
                    size: [50, 50],
                    zindex: 1,
                },{
                    url: require('../../assets/offline.png') , 
                    anchor: [25, 50],
                    size: [50, 50],
                    zindex: 1,
                },{
                    url:require('../../assets/abnormal.png') ,  
                    anchor:  [25, 50],
                    size: [50, 50],
                    zindex: 1,
                },{
                    url:  require('../../assets/onlinestar.png') ,
                    anchor: [15, 15],
                    size: [30, 30],
                    zindex: 1,
                }
            ],
        };
    },
    mounted(){
      this.initamap();
    },      
    methods: {
    	initamap(){
    		amaploader.load({
                key: "申请好的web端开发者key", // 申请好的web端开发者key,首次调用 load 时必填
                version: "2.0", // 指定要加载的 jsapi 的版本,缺省时默认为 1.4.15
                plugins: ["amap.scale", "amap.toolbar", "amap.controlbar", 'amap.geocoder', 'amap.marker','amap.citysearch', 'amap.geolocation', 'amap.autocomplete', 'amap.infowindow','amap.indexcluster','amap.districtsearch'], // 需要使用的的插件列表, 
            }).then((amap) => {
                // 获取到作为地图容器的dom元素,创建地图实例
                window.map = new amap.map("amapcontainer", { //设置地图容器id
                    resizeenable: true, //是否监控地图容器尺寸变化
                    zoomenable: true, // 地图是否可缩放,默认值为true
                    dragenable: true, // 地图是否可通过鼠标拖拽平移,默认为true
                    doubleclickzoom: true, // 地图是否可通过双击鼠标放大地图,默认为true
                    zoom: 11, //初始化地图级别
                    center: [121.59996, 31.197646], // 初始化中心点坐标 上海
                    mapstyle: "amap://styles/dark", // 设置颜色底层
                })
                this.initdistrict();
                this.initpoints();
                this.executeconditionrender();
                //监听地图缩放或者地图平移事件,当缩放或平移时判断层级展示聚合点或海量点
                window.map.on('zoomend', () => { // 监听地图缩放结束后的等级
		            this.executeconditionrender();
		         });
		        window.map.on('moveend', () => { // 监听地图中心点的位置变化
		            this.executeconditionrender();
		        })
            }).catch(e => {
                console.log(e)
            })
    	},
    	//调用后端接口初始化省市区数据返回this.areadata;
    	/*
    	返回的数据格式如下
    	areadata:[
    	   '上海':{
		    	adcode:'310000',   //高德提供的adcode数据
		    	center:'121.473667,31.230525',
				...  //其他隐藏
			},
			...//其他省市区类似
		]
		*/
    	initdistrict(){
   			...  
    		return this.areadata
    	},
    	//调用后端接口初始化省市区数据返回this.points;
    	/*
    	返回的数据格式如下
    	points:[
    		{
		    	lnglat:"121.59996, 31.197646", //经纬度数据
		    	style:0,  //用于海量点样式数组中使用哪一个数据
				id:'1',  //数据id
				...  //其他隐藏
			},
			...//其他点位类似
		]
		*/
    	initpoints(){
    		...  
    		return this.points;
    	}
	}
}
  1. 自定义索引聚合及其样式,并且聚合点点击效果,参考高德示例按索引聚合
//初始化聚合对象
initindexcluster(){
    var vuethis=this;
    window.indexcluster?(window.indexcluster.setmap(null),window.indexcluster =null):"";
    window.map.plugin(['amap.indexcluster'],function(){
        window.indexcluster = new amap.indexcluster(window.map, vuethis.points,{
            renderclustermarker: vuethis._renderclustermarker,
            clusterindexset: vuethis.clusterindexset        
        });
    })
},
//聚合效果样式
getstyle(context) {
    var clusterdata = context.clusterdata; // 聚合中包含数据
    var index = context.index; // 聚合的条件
    var count = context.count; // 聚合中点的总数
    var marker = context.marker; // 聚合绘制点 marker 对象
    var color = [
        '8,60,156',
        '66,130,198',
        '107,174,214',
        '78,200,211',
    ];
    var indexs = ['province','city','district'];
    var i = indexs.indexof(index['mainkey']);
    var text = clusterdata[0][index['mainkey']];
    var size =85
    if(i <= 2){
        text = '<span class="showname">'+ text+'('+context.count +')'+'</span>';
    } else {
        size = 12 * text.length + 20;
    }
    var style = {
        bgcolor: 'rgba(' + color[i] + ',.8)',
        bordercolor: 'rgba(' + color[i] + ',1)',
        text: text,
        size: size,
        index: i,
        color: '#ffffff',
        textalign: 'center',
        boxshadow: '0px 0px 5px rgba(0,0,0,0.8)'
    }
    return style;
},
//聚合显示位置
getposition(context) {
    var key = context.index.mainkey;
    var dataitem = context.clusterdata && context.clusterdata[0];
    var districtname = dataitem[key];
    if(!this.areadata[districtname]) {
        return null;
    }
    
    var center = this.areadata[districtname].center.split(',');
    var centerlnglat = new amap.lnglat(center[0], center[1]);
     
    return centerlnglat;
},

// 自定义聚合点样式
_renderclustermarker (context) {
    var vuethis=this;
    var clusterdata = context.clusterdata; // 聚合中包含数据
    var index = context.index; // 聚合的条件
    var count = context.count; // 聚合中点的总数
    var marker = context.marker; // 聚合点标记对象
    var styleobj = this.getstyle(context);
    // 自定义点标记样式
    var div = document.createelement('div');
    div.classname = 'amap-cluster';
    div.style.backgroundcolor = styleobj.bgcolor;
    div.style.width = styleobj.size + 'px';
    if(styleobj.index <= 2) {
        div.style.height = styleobj.size + 'px';
        //添加聚合点点击事件,省市聚合点点击显示下一级聚合情况,区级聚合点点击后显示区县范围。
        context.marker.on('click', function(e) {
            var curzoom = window.map.getzoom();
            switch(index.mainkey){
                case 'province':
                    curzoom=6;
                    break;
                case 'city':
                    curzoom=9;
                    break;
                default:
                    curzoom=11;
                    break;
            }
            window.map.setzoomandcenter(curzoom, e.lnglat);
            if(index.mainkey=='district'){
                vuethis.getdistrictboundary(clusterdata[0]['district'])
            }
        });
    }
    div.style.display='flex';
    div.style.justifycontent="center";
    div.style.alignitems="center";
    div.style.border = 'solid 1px ' + styleobj.bordercolor;
    div.style.borderradius = styleobj.size + 'px';
    div.innerhtml = styleobj.text;
    div.style.color = styleobj.color;
    div.style.textalign = styleobj.textalign;
    div.style.boxshadow = styleobj.boxshadow;
    context.marker.setcontent(div)
    // 自定义聚合点标记显示位置
    var position = this.getposition(context);
    if(position){
        context.marker.setposition(position);
    }
    context.marker.setanchor('center');
},
//通过区县名查询区县范围并展示
getdistrictboundary(name){
    var vuethis=this;
    var opts = {
        level :'country',   //关键字对应的行政区级别, country表示全国
        extensions: 'all',  //返回行政区边界坐标组等具体信息
        level: 'district'  //查询行政级别为 区
    };
    var district = new amap.districtsearch(opts);//注意:需要使用插件同步下发功能才能这样直接使用
    district.search(name, function (status, result) {
        if (vuethis.polygon) {
            window.map.remove(vuethis.polygon)//清除上次结果
            vuethis.polygon = null;
        }
        if (!result || !result.districtlist || !result.districtlist[0]) {
            vuethis.$message({ message: '请确认区县名称是否正确', type: "error" });
            return
        }
        var bounds = result.districtlist[0].boundaries;
        if (bounds) {
        //生成行政区划polygon
            for (var i = 0; i < bounds.length; i += 1) {//构造multipolygon的path
                bounds[i] = [bounds[i]]
            }
            vuethis.polygon = new amap.polygon({
                strokeweight: 1,
                path: bounds,
                fillopacity: 0.4,
                fillcolor: '#80d8ff',
                strokecolor: '#0091ea'
            });
            window.map.add(vuethis.polygon)
            window.map.setfitview(vuethis.polygon);//视口自适应
        }
    })
},
  1. 初始化海量点及其样式
//初始化海量点对象
initmassmarks(points,style,zooms){
     var mass= new amap.massmarks(points, {
         opacity:1,
         style:style,
         zooms:zooms
     })
     mass.on('click',function(e){
         vuethis.showwindow(e.data);  //点击海量点展示数据窗口,代码省略。
     })
     mass.setmap(window.map);
},
  1. 实现分级显示聚合点或海量点
    思路:判断当前层级,如果层级<10(省市区层级),则初始化聚合对象病展示在地图上。若层级>10则初始化海量点,这里出现过卡顿,故而选择分片渲染方式。具体可见高德地图海量点massmarks使用卡顿问题记录及解决办法
executeconditionrender() {
    let zoom=window.map.getzoom();
    this.currentzoom=zoom;
    if(zoom<10){    //省市区层级
        if(window.indexcluster==null){
            this.initindexcluster()
        }
        if(zoom<8 && window.polygon){  //省市层级
            window.map.remove(window.polygon)//清除上次结果
            window.polygon = null;
        }
    }else{    //设备层级
        let screencoordinaterange = window.map.getbounds()
        let northeast = [screencoordinaterange.northeast.lng, screencoordinaterange.northeast.lat]
        let southeast = [screencoordinaterange.southwest.lng, screencoordinaterange.northeast.lat]
        let southwest = [screencoordinaterange.southwest.lng, screencoordinaterange.southwest.lat]
        let northwest = [screencoordinaterange.northeast.lng, screencoordinaterange.southwest.lat]

        let screenlist = this.points.filter(item => {  //选择在浏览器视框区域内点位数据
            return item.lnglat!=undefined?amap.geometryutil.ispointinring(item.lnglat, [northeast, southeast, southwest, northwest]):false
        })
        window.mass!=undefined&&window.mass!=null?window.mass.clear():""  //海量点存在则清除
        window.mass=this.initmassmarks(screenlist,this.pointstyles,[10,20])
    }
},

实现效果

  1. 省级截图
    在这里插入图片描述

  2. 市级截图
    在这里插入图片描述

  3. 区级截图
    在这里插入图片描述
    区级点击效果
    在这里插入图片描述

  4. 海量点截图
    在这里插入图片描述

小结

1.记录开发过程中遇到的问题,多研究开发手册。
2.样式效果有些不好看,初始版暂定这个,其他样式效果在此版本上更新。

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com