【vue使用高德地图api,鼠标绘图工具与点聚合插件的浅结合】鼠标绘制矩形,框选地图并放大显示矩形内的点聚合(拓展:点击标记点,可以拿到你的原始数据,去做对应处理)

标题

【vue使用高德地图api,鼠标绘图工具与点聚合插件的浅结合】
用鼠标绘制矩形,框选地图并放大显示矩形内的点聚合(拓展:点击标记点,可以拿到你的原始数据,去做对应处理)

背景

小编目前也是在学习高德api,偶然想到,如果地图上有很多的点聚合在一起,那能不能通过鼠标绘图,画一个矩形框选放大地图上的点聚合,有了这个想法就开干!百度了很久没有满意的答案,可能是我百度的姿势不对吧。于是决定自己动手做一个。

其他

我使用的数绘图工具,只是一个学习,如果不想要这么复杂的绘图,也可以试试官方的拉框缩放,效果也是一样的,官方示例

一睹为快的效果图

在这里插入图片描述
画的矩形

这是原始数据

在这里插入图片描述

一、引入高德地图

1、在高德地图——控制台——获取key

传送门:高德地图
登陆后打开控制台
在这里插入图片描述
创建应用
在这里插入图片描述
添加服务,获取密钥
在这里插入图片描述
在这里插入图片描述

2、npm 安装

这里来个官方文档的传送门:高德地图api

npm i @amap/amap-jsapi-loader --save

3、版本注意,是 2.0!!!!!!

本篇文章使用的是 2.0版本,如果在官网上找示例或者查看文档的时候很容易找错了,尤其是示例,2.0示例直通车2.0参考手册

二、上代码,完整代码也有注释,可以直接跳过这一步

1、创建一个index.vue文件

这是html部分

<template>
    <div class="map_box">
    <!--这个是地图容器,这个id是可以随意改写的,但是一定要记住要和js的初始化map获取的id相同-->
        <div id="container"></div> 
      <!-- 下面的是一个单选控件按钮,是小编之前学习api的时候做的,包涵多个鼠标绘制工具的样式,也配对了对应的切换事件函数,不需要的你们可以自行删除 -->
        <div class="cover"> 
            <el-radio-group v-model="radio" size="mini" @change="draw">
                <el-radio v-for="(item) of radioGroup" :key="item.value" :label="item.value" border>{
   
   {item.name}}</el-radio>
            </el-radio-group>
            <div class="input-item">
                <el-button type="primary" round @click="clearDraw">清除</el-button>
                <el-button type="primary" round @click="closeDraw">关闭绘图</el-button>
            </div>
        </div>
    </div>
</template>

这是我用到的数据

 points: [ // 这个数据是小编随便捏的,具体看后端怎么给你值
                    {
    
    id: 123,lnglat: [118.118547,24.475637]},
                    // 这里的id,是用于做点击标记点做下一步处理的,如果不需要可以删除
                    {
    
    id: 456,lnglat: [118.081211,24.493369]}, 
                    {
    
    lnglat: [118.08885,24.494072]},
                    {
    
    lnglat: [118.09503,24.48962]},
                    {
    
    lnglat: [118.102926,24.48837]},
                    {
    
    lnglat: [118.08679,24.485402]},
                    {
    
    lnglat: [118.081941,24.485909]},
                    {
    
    lnglat: [118.090137,24.476614]},
                    {
    
    lnglat: [118.094171,24.475598]},
                    {
    
    lnglat: [118.089794,24.472708]},
                    {
    
    lnglat: [118.094987,24.480051]},
                    {
    
    lnglat: [118.083614,24.47802]},
                    {
    
    lnglat: [118.09606,24.48298]},
                    {
    
    lnglat: [118.10181,24.478215]},
                    {
    
    lnglat: [118.083829,24.477864]},
                    {
    
    lnglat: [118.137158,24.451969]},
                    {
    
    lnglat: [118.144797,24.452047]},
                    {
    
    lnglat: [118.14351,24.445562]},
                    {
    
    lnglat: [118.114928,24.446812]},
                    {
    
    lnglat: [118.106879,24.453121]},
                    {
    
    lnglat: [118.103618,24.455934]},
                    {
    
    lnglat: [118.114261,24.457731]},
                    {
    
    lnglat: [118.12184,24.457445] },
                    {
    
    lnglat: [118.13044,24.456637]},
                    {
    
    lnglat: [118.112738,24.446725]},
                    {
    
    lnglat: [118.104035,24.442895]},
                    {
    
    lnglat: [118.12364,24.444474]},
                    {
    
    lnglat: [118.12673,24.443168]},
                ],

在你的页面中引入刚才安装的依赖,哪里用就哪里引。

    import AMapLoader from "@amap/amap-jsapi-loader";

2、修改刚才从官网获取的key

除了安装那一步,直接复制第五步完整代码黏贴,妥妥的

AMapLoader.load({
    
    
    key: "这里填写你的key", //此处填入我们注册账号后获取的Key
    version: "2.0", //指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
    plugins: ['AMap.AutoComplete','AMap.PlaceSearch','AMap.MarkerClusterer','AMap.DistrictSearch','AMap.MouseTool'], //需要使用的的插件列表,如比例尺'AMap.Scale'等
 })

3、如何获取原数据? 往下看

     // 设置点聚合的点击事件,在这里你可以根据你原数据的id,去做你想做的事,我就不明说了
    cluster.on("click", data => {
    
    
        // console.log("click", data);
        const {
    
    clusterData} = data;
        console.log(clusterData); // 原始数据,这里打印的就是你的原始数据!!!!!
    })

四、注意事项

我的示例中,右上角的菜单板块 有用到element-ui的单选框组件和按钮,主要是方便,不用手写一套,如果你要完整使用我的示例,需要先安装element-ui,百度一下,很多安装方法,如果你不需要,自己修改一下我的代码也可以用
还有就是
目前这个菜单板块,只有做了⚪和矩形的放大,其他只是玩玩测试而已!!!!!!!!!!!!!

小tips: 绘制时是以单击右键结束
在这里插入图片描述

五、完整的代码

一定要先去高德官网获取key,再安装,再复制代码黏贴,然后需修改你的key

<template>
    <div class="map_box" style="z-index: 2;  overflow: hidden;">
        <div id="container"></div>
        <div class="cover">
            <el-radio-group v-model="radio" size="mini" @change="draw">
                <el-radio v-for="(item) of radioGroup" :key="item.value" :label="item.value" border>{
    
    {
    
    item.name}}</el-radio>
            </el-radio-group>
            <div class="input-item">
                <el-button type="primary" round @click="clearDraw">清除</el-button>
                <el-button type="primary" round @click="closeDraw">关闭绘图</el-button>
            </div>
<!--            asdasd-->
        </div>
    </div>
</template>
<script>
    import AMapLoader from "@amap/amap-jsapi-loader";
    export default {
    
    
        name: "diviceMap",
        data(){
    
    
            return {
    
    
            // 有些定义的是我之前用的的变量,看你们需不需要,不需要可以删除
                map: null,
                maker: null,
                marker: [118.118174, 24.468552],
                markers: [],
                icon: null,
                isShow: false,
                out: true,
                mapModule: null, // AMap
                radioGroup: [
                    {
    
    name: '画点', value: 'marker'},
                    {
    
    name: '画折线', value: 'polyline'},
                    {
    
    name: '画多边形', value: 'polygon'},
                    {
    
    name: '画矩形', value: 'rectangle'},
                    {
    
    name: '画圆', value: 'circle'},
                ],
                radio: '',
                mouseTool: null, // 鼠标绘图工具
                overlays: [], // 覆盖物 获取的点 / 路径参数 数组
                center: [118.126078, 24.459206],
                zoom: 12, //初始化地图级别
                cluster: null, // 点聚合
                points: [ // 这个数据是小编随便捏的,具体看后端怎么给你值
                    {
    
    id: 123,lnglat: [118.118547,24.475637]},
                    // 这里的id,是用于做点击标记点做下一步处理的,如果不需要可以删除
                    {
    
    id: 456,lnglat: [118.081211,24.493369]}, 
                    {
    
    lnglat: [118.08885,24.494072]},
                    {
    
    lnglat: [118.09503,24.48962]},
                    {
    
    lnglat: [118.102926,24.48837]},
                    {
    
    lnglat: [118.08679,24.485402]},
                    {
    
    lnglat: [118.081941,24.485909]},
                    {
    
    lnglat: [118.090137,24.476614]},
                    {
    
    lnglat: [118.094171,24.475598]},
                    {
    
    lnglat: [118.089794,24.472708]},
                    {
    
    lnglat: [118.094987,24.480051]},
                    {
    
    lnglat: [118.083614,24.47802]},
                    {
    
    lnglat: [118.09606,24.48298]},
                    {
    
    lnglat: [118.10181,24.478215]},
                    {
    
    lnglat: [118.083829,24.477864]},
                    {
    
    lnglat: [118.137158,24.451969]},
                    {
    
    lnglat: [118.144797,24.452047]},
                    {
    
    lnglat: [118.14351,24.445562]},
                    {
    
    lnglat: [118.114928,24.446812]},
                    {
    
    lnglat: [118.106879,24.453121]},
                    {
    
    lnglat: [118.103618,24.455934]},
                    {
    
    lnglat: [118.114261,24.457731]},
                    {
    
    lnglat: [118.12184,24.457445] },
                    {
    
    lnglat: [118.13044,24.456637]},
                    {
    
    lnglat: [118.112738,24.446725]},
                    {
    
    lnglat: [118.104035,24.442895]},
                    {
    
    lnglat: [118.12364,24.444474]},
                    {
    
    lnglat: [118.12673,24.443168]},
                ],
                gridSize: 120, // 设置网格像素大小
            }
        },
        methods: {
    
    
        // 初始化地图
            initMap() {
    
    
                let that = this;
                AMapLoader.load({
    
    
                    key: "这里填写你的key", //此处填入我们注册账号后获取的Key
                    version: "2.0", //指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
                    plugins: ['AMap.AutoComplete','AMap.PlaceSearch','AMap.MarkerClusterer','AMap.DistrictSearch','AMap.MouseTool'], //需要使用的的插件列表,如比例尺'AMap.Scale'等
                }).then((AMap) => {
    
    
                    that.mapModule = AMap; // 将它赋值给定义的变量,以便后续其他方法需要使用
                    that.map = new AMap.Map("container", {
    
     //设置地图容器id
                        viewMode: "3D", //是否为3D地图模式
                        zoom: that.zoom, //初始化地图级别
                        center: that.center, //初始化地图中心点位置
                    });
                    // 地图点击事件,这是之前小编用来获取经纬度
                    // 要使用showInfoClick函数,要先把下面的注释代码解了
                    // that.map.on('click', that.showInfoClick);
					
					// 创建鼠标绘图工具
                    that.mouseTool = new AMap.MouseTool(that.map);
                    // 添加绘制事件
                    that.mouseTool.on('draw', that.drawOverlays);
                    // 这里由于是高德2.0,升级的版本,不再像原来那样需要繁琐的先构造marker点,直接放入带有经纬度的数据就可以了,具体内容请查看官方文档的升级指南
                    that.cluster = new AMap.MarkerCluster(that.map,that.points,{
    
    
                        renderClusterMarker: that.renderClusterMarker,// 自定义聚合点样式
                        gridSize: that.gridSize, // 设置网格像素大小
                        renderMarker: that.renderMarker, // 自定义非聚合点样式
                    });

                     // 如何获取原数据? 往下看

                    // 设置点聚合的点击事件,在这里你可以根据你原数据的id,去做你想做的事,我就不明说了
                    that.cluster.on("click", data => {
    
    
                        // console.log("click", data);
                        const {
    
    clusterData} = data;
                        console.log(clusterData); // 原始数据,这里打印的就是你的原始数据!!!!!
                    })
                }).catch(e => {
    
    
                    console.log(e);
                })
            },

            // 自定义聚合点样式,这两个自定义样式事件看不懂没关系,反正照着抄就行,需要的改一改颜色就好了
            // 但是这个事件里面有一个自定义点击事件要看一下!!!
            renderClusterMarker(context) {
    
    
                let that = this;
                let count = that.points.length;
                let factor = Math.pow(context.count / count, 1 / 18);
                let div = document.createElement('div');
                let Hue = 180 - factor * 180;
                let bgColor = 'hsla(' + Hue + ',100%,40%,0.7)';
                let fontColor = 'hsla(' + Hue + ',100%,90%,1)';
                let borderColor = 'hsla(' + Hue + ',100%,40%,1)';
                let shadowColor = 'hsla(' + Hue + ',100%,90%,1)';
                div.style.backgroundColor = bgColor;
                let size = Math.round(30 + Math.pow(context.count / count, 1 / 5) * 20);
                div.style.width = div.style.height = size + 'px';
                div.style.border = 'solid 1px ' + borderColor;
                div.style.borderRadius = size / 2 + 'px';
                div.style.boxShadow = '0 0 5px ' + shadowColor;
                div.innerHTML = context.count;
                div.style.lineHeight = size + 'px';
                div.style.color = fontColor;
                div.style.fontSize = '14px';
                div.style.textAlign = 'center';
                context.marker.setOffset(new that.mapModule.Pixel(-size / 2, -size / 2));
                context.marker.setContent(div)
         
				// 自定义点击事件,这边做的是点击聚合点,以聚合点中心,放大一级
                context.marker.on('click', function(e) {
    
    
                    console.log(e)
                    let curZoom = that.map.getZoom(); 
                    if(curZoom < 20){
    
    
                        curZoom += 1;
                    }
                    that.map.setZoomAndCenter(curZoom, e.lnglat);
                });
            },
            // 自定义非聚合点样式
            renderMarker(context){
    
    
                let content = '<div style="background-color: hsla(180, 100%, 50%, 0.3); height: 18px; width: 18px; border: 1px solid hsl(180, 100%, 40%); border-radius: 12px; box-shadow: hsl(180, 100%, 50%) 0px 0px 3px;"></div>';
                let offset = new this.mapModule.Pixel(-9, -9);
                context.marker.setContent(content)
                context.marker.setOffset(offset)
            },	
            
			// 绘画工具切换
            draw(type){
    
    
                switch(type){
    
    
                    case 'marker':{
    
    
                        this.mouseTool.marker({
    
    
                            //同Marker的Option设置
                        });
                        break;
                    }
                    case 'polyline':{
    
    
                        this.mouseTool.polyline({
    
    
                            strokeColor:'#80d8ff'
                            //同Polyline的Option设置
                        });
                        break;
                    }
                    case 'polygon':{
    
    
                        this.mouseTool.polygon({
    
    
                            fillColor:'#00b0ff',
                            strokeColor:'#80d8ff'
                            //同Polygon的Option设置
                        });
                        break;
                    }
                    case 'rectangle':{
    
    
                        this.mouseTool.rectangle({
    
    
                            fillColor:'#00b0ff',
                            strokeColor:'#80d8ff'
                            //同Polygon的Option设置
                        });
                        break;
                    }
                    case 'circle':{
    
    
                        this.mouseTool.circle({
    
    
                            fillColor:'#00b0ff',
                            strokeColor:'#80d8ff'
                            //同Circle的Option设置
                        });
                        break;
                    }
                }
            },
            drawOverlays(e) {
    
    
                // console.log(e);//获取路径
                this.overlays.push(e.obj);
                if (this.radio === 'marker') {
    
    
                    console.log(e.obj)
                }else if(this.radio === 'circle'){
    
    
                // ⚪也有 getBounds()方法
                    console.log(e.obj.getRadius());//获取半径
                    console.log(e.obj.getCenter());//获取中心点
                    let curZoom = this.map.getZoom();
                    if(curZoom > 5){
    
    
                        curZoom -= 1;
                    }
                    this.map.setZoomAndCenter(curZoom, e.obj.getCenter());
                    // this.clearDraw();
                }else {
    
    
                    let northEast = [e.obj.getBounds().northEast.lng,e.obj.getBounds().northEast.lat];
                    let southWest = [e.obj.getBounds().southWest.lng,e.obj.getBounds().southWest.lat]
                    console.log(e.obj.getBounds())
                    let mybounds = new this.mapModule.Bounds(northEast, southWest);
                    this.map.setBounds(mybounds);
                }
            },
            // 清除覆盖物
            clearDraw(){
    
    
                this.map.remove(this.overlays)
                this.overlays = [];
            },
            //关闭,并清除覆盖物
            closeDraw(){
    
    
                this.mouseTool.close(true);//关闭,并清除覆盖物
                this.radio= '';
            },
                // 获取点击时的坐标,这个函数要使用要把初始化的添加点击事件的代码取消注释
             showInfoClick(e){
    
    
                let lnglat = [e.lnglat.getLng(),e.lnglat.getLat()]
                 console.log(lnglat)
                this.points.push({
    
    lnglat:lnglat})
                 console.log(this.points)
            }

        },
        mounted() {
    
    
            //挂载阶段调用,DOM初始化完成进行地图初始化
            this.initMap();
        }
    }
</script>
<style scoped>
    .map_box {
    
    
        /*position: absolute;*/
        /*top: -30px;*/
        width: 100%;
        /*border-radius: 50%;*/
    }

    #container {
    
    

        padding: 0px;
        margin: 0px;
        width: 100%;
        /*height: 100vh ;*/
        height: calc(100vh - 4.4rem);

    }

    .cover {
    
    
        position: absolute;
        top: 10px;
        background-color: #ffffff;
        z-index: 15;
        width: 300px;
        padding: 10px;
        /*height: 40px;*/
        /*border: 2px solid #265abf;*/
        right: 10px;
        box-shadow: 0 0 10px 0 rgba(203, 203, 203, 0.3);
        border-radius: 5px;
    }

    .cover .el-radio {
    
    
        margin-right: 5px;
        margin-bottom: 5px;
    }

    /deep/ .cover .el-radio.is-bordered + .el-radio.is-bordered {
    
    
        margin-left: 0;
    }

    /deep/ .cover .input-item .el-button.is-round {
    
    
        padding: 5px 10px;
    }

    .cover .input-item {
    
    
        /*text-align: right;*/
        display: flex;
        justify-content: space-around;
    }
</style>

猜你喜欢

转载自blog.csdn.net/Fantasywt/article/details/125990091
今日推荐