Vue中使用高德地图官方AMapUI 组件库(非第三方组件库) 实现行政区划聚合+海量点展示

2,303 阅读2分钟

Vue中安装高德地图

JS API 2.0 版本提供了两种方案引入地图 JSAPI:

  1. 使用官网提供的 JSAPI Loader 进行加载;
  1. 以常规 JavaScript 脚本的方式加载;

注意:为避免地图数据协议和前端资源不匹配导致页面运行报错,只允许在线加载 JSAPI,禁止进行本地转存、与其它代码混合打包等用法。

官方JSAPI的加载文档

本文使用 JSAPI Loader (推荐)

JSAPI Loader是我们提供的 API 加载器,可帮助开发者快速定位、有效避免加载引用地图 JSAPI 各种错误用法,具有以下特性:

  • 支持以 普通JS 和 npm包 两种方式使用;
  • 有效避免错误异步加载导致的 JSAPI 资源加载不完整问题;
  • 对于加载混用多个版本 JSAPI 的错误用法给予报错处理;
  • 对于不合法加载引用 JSAPI 给予报错处理;
  • 支持指定 JSAPI 版本;
  • 支持插件加载;
  • 允许多次执行加载操作,网络资源不会重复请求,便于大型工程模块管理;
  • 支持IE9以上的浏览器,不支持IE8以下

按 NPM 方式使用 Loader

安装:

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

使用:

HTML5

<!--地图容器-->
<div id="container"></div>

CSS3

<style lang="scss">
 #container {
   width: 100%;
   height: calc(100vh - 281px);
}
</style>

JavaScript

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

AMapLoader.load({
    "key": "",              // 申请好的Web端开发者Key,首次调用 load 时必填
    "version": "2.0",   // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
    "plugins": [],           // 需要使用的的插件列表,如比例尺'AMap.Scale'等
}).then((AMap)=>{
    map = new AMap.Map('container');
}).catch(e => {
    console.log(e);
})

正文开始:行政区划聚合+海量点展示(全部代码)

<template>
  <div class="equipment">
<!--    地图容器-->
    <div id="container"></div>
  </div>
</template>
<script>
import AMapLoader from '@amap/amap-jsapi-loader';
import axios from 'axios'

let map = null
export default {
  name: 'index',
  beforeCreate() {},
  data() {
    return {
    }
  },
  created() {
  },
  mounted() {
    //DOM初始化完成进行地图初始化
    this.initMap();
  },
  computed() {
  },
  methods: {
    initMap(){
      AMapLoader.load({
        key:"",             // 申请好的Web端开发者Key,首次调用 load 时必填
        version:"2.0",      // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
        plugins:['AMap.Scale', 'AMap.Marker', 'AMap.InfoWindow', 'AMap.MarkerCluster'],
        AMapUI: {
          version: '1.1',
          plugins:['overlay/SimpleMarker']
        }// 需要使用的的插件列表,如比例尺'AMap.Scale'等
      }).then((AMap)=>{
        map = new AMap.Map("container",{  //设置地图容器id
          viewMode:"2D",    //是否为3D地图模式
          terrain: false, // 开启地形图
          // pitch:75, // 地图俯仰角度,有效范围 0 度- 83 度
          zoom:4,           //初始化地图级别
          center:[105.602725,37.076636], //初始化地图中心点位置
        });
        this.aMapUiLoad()
      }).catch(e=>{
        console.log(`高德地图加载错误提示${e}`); //加载错误提示
      })
    },
    // 区划聚合+海量点展示
    initPage(DistrictCluster, PointSimplifier) {

        var pointSimplifierIns = new PointSimplifier({
          map: map, //所属的地图实例
          autoSetFitView: false, //禁止自动更新地图视野
          zIndex: 110,
          getPosition: function(item) {

            if (!item) {
              return null;
            }

            var parts = item.split(',');

            //返回经纬度
            return [parseFloat(parts[0]), parseFloat(parts[1])];
          },
          getHoverTitle: function(dataItem, idx) {
            // return idx + ': ' + dataItem;
            return `<div style="height: 12vh;width: 16vw;background-color:#FFFFFF;margin:0;padding:0;z-index:9999999">
                      <h2>第${idx}台设备</h2>
                      <p>
                         设备简介
                      </p>
                    </div>`
          },
          renderOptions: {
            //点的样式
            pointStyle: {
              width: 6,
              height: 6,
              fillStyle:'rgba(153, 0, 153, 0.38)'
            },
            //鼠标hover时的title信息
            hoverTitleStyle: {
              position: 'top'
            },
          }
        });

        var distCluster = new DistrictCluster({
          zIndex: 100,
          map: map, //所属的地图实例

          getPosition: function(item) {

            if (!item) {
              return null;
            }

            var parts = item.split(',');

            //返回经纬度
            return [parseFloat(parts[0]), parseFloat(parts[1])];
          },
          renderOptions: {
            getFeatureStyle: function(feature, dataItems) {

              if (dataItems.length > 3000) {

                return {
                  fillStyle: 'rgba(57, 57, 255, 0.8)'
                };

              } else if (dataItems.length > 1000) {
                return {
                  fillStyle: 'rgba(91, 91, 255, 0.7)'
                };
              }else if (dataItems.length > 500) {
                return {
                  fillStyle: 'rgba(107, 107, 255, 0.6)'
                };
              }else if (dataItems.length < 501) {
                return {
                  fillStyle: 'rgba(189, 189, 255, 0.5)'
                };
              }
              return {};
            },
            featureStyle:{
              fillStyle: '',

              lineWidth: 1,

              strokeStyle: 'rgb(92,206,255)',

                hoverOptions:{

                fillStyle:'rgba(189, 189, 255, 0.5)',

                lineWidth: 5,

                strokeStyle:'rgb(255,181,71)'

                }
            },
            featureEventSupport: true,
            clusterMarkerEventSupport: true,
            //标注信息Marker上需要监听的事件
            clusterMarkerEventNames: ['click', 'rightclick', 'mouseover', 'mouseout']
          }
        });

        window.distCluster = distCluster;

        function refresh() {

          var zoom = map.getZoom();

          //获取 pointStyle
          var pointStyle = pointSimplifierIns.getRenderOptions().pointStyle;

          //根据当前zoom调整点的尺寸
          pointStyle.width = pointStyle.height = 2 * Math.pow(1.2, map.getZoom() - 3);
        }

        map.on('zoomend', function() {
          refresh();
        });

        refresh();

        const loading = this.$loading({
          lock: true,
          text: 'Loading',
          spinner: 'el-icon-loading',
          background: 'rgba(0, 0, 0, 0.7)'
        });
        // axios获取十万个经纬度点的text,实际项目中替换成请求后台接口的方法
        let url = 'https://a.amap.com/amap-ui/static/data/10w.txt'
        axios({
          method: 'get',
          url,
          responseType: 'blob',
          transformResponse: [function (data) {
            let reader = new FileReader();
            reader.readAsText(data, 'GBK');
            reader.onload = function () {
              //此处便是返回值
              // console.log(reader.result);
              loading.close();
              let csv = reader.result
              let data = csv.split('\n');

              distCluster.setData(data);

              pointSimplifierIns.setData(data);
            }
            return data;
          }]
        }).then(res => {
          console.log(res.data)
        })
      },
    // 加载(区划聚合+海量点展示)、行政区划相关组件
    aMapUiLoad() {
      AMapUI.load(['ui/geo/DistrictCluster', 'ui/misc/PointSimplifier', 'lib/$'], (DistrictCluster, PointSimplifier) => {

        //启动页面
        this.initPage(DistrictCluster, PointSimplifier);
      });
    }
  }
}
</script>
<style lang="scss">
.equipment {
  #container {
    width: 100%;
    height: 100vh;
  }
}
</style>

注:经笔者实践,到2022/5/28日为止高德3D地图确实不兼容AMapUI中的PointSimplifier(海量点展示组件)与DistrictCluster(行政区聚合组件)

3D 地图兼容性说明

  • 3D地图效果下,如果使用自定义栅格图,需要保证栅格图片服务返回的图片资源是带有 Access-Control-Allow-Origin:* 响应Header的,否则将无法加载自定义栅格图。
  • 3D地图目前兼容windows、Mac、iOS、Android等多平台下的众多浏览器,但是由于地图绘制依赖WebGL等前端环境,如果终端环境无法满足3D绘制的要求,我们将仍然使用原有2D视图进行绘制。
  • JSAPI V1.4.0之后的版本开始支持3D地图,3D视图不支持的 API 接口如下:
名称说明
 AMap.Polygon 带洞多边形的绘制,v1.4.14版本开始支持
 AMap.CloudLayer 云图图层
 PointSimplifier  海量点展示组件 
 PathSimplifier  轨迹展示组件 
 DistrictExplorer  行政区划浏览,v1.4.14版本开始支持
 DistrictCluster  行政区聚合