问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

高德地图聚合点实现:点位热更新与点击交互

创作时间:
作者:
@小白创作中心

高德地图聚合点实现:点位热更新与点击交互

引用
CSDN
1.
https://blog.csdn.net/2302_78685420/article/details/144710759

本文将详细介绍如何使用高德地图API实现聚合点功能,包括点位热更新和点击交互。通过本文,你将学习到如何通过NPM安装Loader,设置key和安全密钥,并掌握完整的代码实现方法。

初始化高德地图

首先,需要通过NPM安装高德地图的Loader:

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

然后在JavaScript中加载地图:

<script setup>
    import AMapLoader from "@amap/amap-jsapi-loader";
    let map = null; //地图实例
    
    onMounted(() => {
        window._AMapSecurityConfig = {
            securityJsCode: "你申请的安全密钥",
        };
        AMapLoader.load({
                key: "替换为你申请的 key", // 申请好的Web端开发者Key,首次调用 load 时必填
                version: "2.0", // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
                plugins: ["AMap.Scale"], //需要使用的的插件列表,如比例尺'AMap.Scale',支持添加多个如:['...','...']
            })
            .then((AMap) => {
                // 设置地图容器id
                map = new AMap.Map("container", {
                    viewMode: "2D", // 是否为3D地图模式
                    zoom: 8, // 初始化地图级别
                    center: [116.397428, 39.90923], // 初始化地图中心点位置
                });
            })
            .catch((e) => {
                console.log(e);
            });
    });
</script>

聚合点样式示例

聚合点及热更新完整代码:

HTML部分

<template>
    <view>
        <view id="container"></view>
    </view>
</template>

CSS部分

<style lang="less" scoped>
    #container {
        width: 100%;
        height: 100%;
    }
</style>

JavaScript部分

<script setup>
    import AMapLoader from "@amap/amap-jsapi-loader";
    import { ref,onMounted,onUnmounted,watch,defineEmits } from "vue";
    // 组件传参聚合点实例
    const props = defineProps({
        points: {
            type: Array,
            //示例代码聚合点位变量规则
            default: () => [
                {
     	            lnglat: ["116.506621867519", "39.925077049391"],
     	            building: "晨光家园",
                    district: "朝阳区",
                    city: "北京",
                 }
            ],
        },
    });
    // 注册组件暴露方法
    const emits = defineEmits(['pointsClick'])
    let map = null; //地图实例
    let indexCluster; //聚合点实例
    //监听点位变化进行点位热更新
    watch(
        () => props.points,
        (newDataArr) => {
            points.value = newDataArr;
            if (map) {
                loadIndexCluster(newDataArr);
            }
        }, {
            immediate: false,
        }
    );
    
    onMounted(() => {
        window._AMapSecurityConfig = {
            securityJsCode: "你申请的安全密钥",
        };
        AMapLoader.load({
                key: "替换为你申请的 key", // 申请好的Web端开发者Key,首次调用 load 时必填
                version: "2.0", // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
                plugins: ["AMap.Scale"], //需要使用的的插件列表,如比例尺'AMap.Scale',支持添加多个如:['...','...']
            })
            .then((AMap) => {
                // 设置地图容器id
                map = new AMap.Map("container", {
                    viewMode: "2D", // 是否为3D地图模式
                    zoom: 8, // 初始化地图级别
                    center: [116.397428, 39.90923], // 初始化地图中心点位置
                });
                map.plugin(["AMap.IndexCluster"], function() {
                    loadIndexCluster(points.value); // 初始加载聚合点
                });
            })
            .catch((e) => {
                console.log(e);
            });
    });
    //定义点聚合规则变量
    let clusterIndexSet = {
        //城市层级
        city: {
            minZoom: 2,
            maxZoom: 10,
        },
        //区/县层级
        district: {
            minZoom: 10,
            maxZoom: 12,
        },
        //具体标点层级
        building: {
            minZoom: 12,
            maxZoom: 22,
        },
    };
    //聚合点样式
    const _renderClusterMarker = function(context) {
        let clusterCount = context.count; //聚合点内点数量
        let clusterData = context.clusterData; //聚合点数组
        let mainKey = context.index.mainKey; //聚合点对应索引
        let constData = clusterData[0][mainKey];//当前层级(市/区)展示名
        // 构建聚合点的显示内容
        let content;
        if (mainKey == "city") {
            //城市样式
            content = `
            <div>
              ${constData}<br>
              ${clusterCount > 1 ? clusterCount : ""}${clusterCount > 1 ? "家" : ""}
            </div>`;
        } else if (mainKey == "district") {
            //区样式
            content = `
              <div>
                ${constData}<br>
                ${clusterCount > 1 ? clusterCount : "1"}${clusterCount > 1 ? "家" : ""}
              </div>`;
        } else {
            //区样式
            let name = clusterData[0].entName || clusterData[0].name;
            content = `
              <div style="position: relative;">
                <img style="width:20px; height: 24px;" src="" alt="" />
                <div>${name}</div>
              </div>`;
        }
        // 自定义点击事件
        context.marker.on("click", function(e) {
            // touchend 移动端点击事件;mouseup pc点击
            let clickType = e.originEvent.type;
            // 兼容pc端、移动端判断
            if (clickType == "touchend" && getDeviceType() == "Mobile") {
                // 移动端
                if (clusterData.length != 0 && mainKey == "building") {
                    setTimeout(() => {
                        emits('pointsClick', clusterData)//向父组件传递点位信息
                    }, 100)
                }
            } else if (clickType == "mouseup" && getDeviceType() == "Desktop") {
                // pc端
                setTimeout(() => {
                    emits('pointsClick', clusterData)//向父组件传递点位信息
                }, 100)
            }
        });
        context.marker.setContent(content);
    };
    // 聚合点图层热更新调用
    const loadIndexCluster = (newPoints) => {
        if (indexCluster) {
            // 销毁现有的 IndexCluster 实例
            indexCluster.setMap(null);
            indexCluster = null;
        }
        indexCluster = new AMap.IndexCluster(map, newPoints, {
            renderClusterMarker: _renderClusterMarker, // 自定义聚合点样式
            clusterIndexSet: clusterIndexSet, // 聚合规则
        });
    };
    // 判断当前设备类型
    function getDeviceType() {
        const userAgent = navigator.userAgent;
        // 判断是否是移动设备(手机或平板)
        if (
            /Mobi|Android|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(
                userAgent
            )
        ) {
            return "Mobile";
        }
        // 默认是电脑
        return "Desktop";
    }
    onUnmounted(() => {
        map?.destroy();//释放内存销毁实例
    });
</script>

注意事项

  • 该项目样式简单直接采用模板字符串插入dom,样式复杂的建议写好点位样式获取dom节点;
  • 点击事件加延迟避免触发/影响父组件遮罩点击事件,可采用preventDefault()(e.originEvent.preventDefault();)方法替换定时器延迟调用;
© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号