VUE中使用高德地图(原生UI,信息窗体内部事件监听)

2023-11-15

VUE中使用高德地图(原生UI)

先吐槽一下,本人的环境是基于vue3.0的项目,上一位参与项目的同事使用的事vue-amap,因工作需要,另外一位同事去了别的项目,所以这个万恶的项目由本人自己维护,就是再本周新增了需求,根据不用大区的用户进入到系统,显示不同的地图边界。 由也正因为于本人能力有限,未能基于vue-amap实现新增的需求,所以考虑使用原生UI功能,但因为引入原生UI与与原生UI冲突,总是报错,所以被本人放弃第三方组件方式,直接使用原生UI来进行开发。

遇到的问题(后面会详细解说)

  1. 自定义窗体问题;
  2. 窗体内部事件监听问题;
  3. 根据坐标获取Address问题;
  4. 获取省份行政区划代码问题;
  5. 行政区划添加图层展示问题;

问题内容解说前,先插入一点题外话,就是如何看API,高德地图功能很强大,据说什么样的地图都可以实现。
首先,高德地图有示例中心,有普通JS的示例,原生UI的示例,那我们要看的部分就是原生UI的示例+高德地图(WebJs API)
这里附上地址:
高德地图组件UI示例地址:https://lbs.amap.com/api/amap-ui/demos/amap-ui-districtexplorer/multi-load
高德地图JSAPI地址:https://lbs.amap.com/api/javascript-api/summary
下面针对遇到的问题开始进行详细解说,以代码为主。

本人所有功能的代码

main.js 中引入的高德地图插件(项目中是使用了vue-amap这个第三方插件的)
代码如下:

import VueAMap from 'vue-amap';
Vue.use(VueAMap);
VueAMap.initAMapApiLoader({
  key: '申请开发Web版地图的Key,再高德地图官方网站进行申请',
  plugin: ['AMap.Scale', 'AMap.OverView', 'AMap.Geolocation'],
  v: '1.4.4',
  uiVersion: '1.0.11' // UI版本号
});

包含地图所有功能的vue文件UIMap.vue

<template>
  <div class="uimap">
    <div id="uimap" class="amap-box"></div>
  </div>
</template>

<script>
import vm from '@/libs/vm';
import { USER_MIXINS } from '@/libs/mixins';
import NoNet from '@/assets/images/no-net.png';
import HasNet from '@/assets/images/has-net.png';
import Normal from '@/assets/images/Normal.png';
import Middle from '@/assets/images/Middle.png';
import Interrupt from '@/assets/images/Interrupt.png';
import Unknown from '@/assets/images/Unknown.png';
import { AMapManager, lazyAMapApiLoaderInstance } from 'vue-amap';
import $ from 'jquery';
import { type } from 'os';
let amapManager = new AMapManager();
const loadPromise = lazyAMapApiLoaderInstance.load();
export default {
  mixins: [USER_MIXINS],
  data() {
    let self = this;
    return {
      a_provincecode: [],
      districtExplorer: {},
      locationInfo: {},
      simpleInfoWindow: null,
      amapManager: amapManager,
      map: null,
      zoom: '',
      center: [116.50436, 39.78634],
      markers: [],
      lng: 0,
      lat: 0,
      areaName: '',
      dataCount: '' // 异常数据条数
    };
  },
  async mounted() {
    this.locationInfo = await this.getFactoryStatesAndAbnormalCount();
    this.$nextTick(() => {
      let aMark = this.markers.forEach(item => {
        return item.position;
      }); // 覆盖默认的dom结构

      loadPromise.then(() => {
        let _self = this;
        var _simpleInfoWindow = {};
        this.map = new AMap.Map('uimap', {
          center: this.center,
          resizeEnable: true
        });
        AMapUI.loadUI(
          [
            'misc/MarkerList',
            'overlay/SimpleMarker',
            'overlay/SimpleInfoWindow',
            'geo/DistrictExplorer'
          ],
          (MarkerList, SimpleMarker, SimpleInfoWindow, DistrictExplorer) => {
            // 创建一个实例
            _self.districtExplorer = new DistrictExplorer({
              map: _self.map
            });
            // just some colors
            var $ = MarkerList.utils.$;
            // 展示所有标记
            var markerList = new MarkerList({
              map: this.map,
              // 从数据中读取位置, 返回lngLat
              getPosition: function(item) {
                return item.position;
              },
              getInfoWindow: function(data, context, recycledInfoWindow) {
                if (recycledInfoWindow) {
                  recycledInfoWindow.setInfoTitle(
                    `<strong class="infoTitle">${
                      data.extData.factoryName
                    }</strong>`
                  );
                  recycledInfoWindow.setInfoBody(
                    `<p class="infoWindow">所在大区:${
                      data.extData.areaName
                    }</p>
                    <p class="infoWindow">异常数据量:${
                      data.extData.abnormalNumber
                    }</p>
                    <p class="infoWindow"><span><a class="goDetail amap-ui-infowindow-close" id="goDetail">详情</a></span><span class="right"><a class="close amap-ui-infowindow-close">关闭</a></span></p>`
                  );
                  return recycledInfoWindow;
                }
                return new SimpleInfoWindow({
                  infoTitle: `<strong class="infoTitle">${
                    data.extData.factoryName
                  }</strong>`,
                  infoBody: `<p class="infoWindow">所在大区:${
                    data.extData.areaName
                  }</p>
                  <p class="infoWindow">异常数据量:${
                    data.extData.abnormalNumber
                  }</p><p class="infoWindow "></span><span><a class="goDetail amap-ui-infowindow-close" id="goDetail" >详情</a></span><span class="right"><a class="close amap-ui-infowindow-close">关闭</a></p>`,
                  offset: new AMap.Pixel(0, -37)
                });
              },
              // 构造marker用的options对象, content和title支持模板,也可以是函数,返回marker实例,或者返回options对象
              getMarker: function(data, context, recycledMarker) {
                let state = data.extData.state;
                return new SimpleMarker({
                  iconStyle:
                    state === 'Interrupt'
                      ? Interrupt
                      : state === 'Middle'
                      ? Middle
                      : state === 'Unknown'
                      ? Unknown
                      : state === 'Normal'
                      ? Normal
                      : Normal,
                  // iconStyle: iconStyle,
                  containerClassNames: 'my-marker'
                });
              },
              // 需要监听的marker事件
              markerEvents: ['click', 'mouseover', 'mouseout'],
              // 需要监听的infoWindow事件
              infoWindowEvents: ['click', 'mouseover', 'mouseout'],
              selectedClassNames: 'selected',
              autoSetFitView: true
            });
            markerList.render(this.markers);
            // 监听选中改变
            markerList.on('selectedChanged', function(event, info) {
              this.simpleInfoWindow = event.target['_singleInfoWindow'];
              if (this.simpleInfoWindow) {
                // 详情按钮监听。。
                this.simpleInfoWindow
                  .get$Container()
                  .on('click', '.goDetail', function(event) {
                    event.stopPropagation();
                    _self.$store.dispatch('setCurrType', 4);
                    _self.routeTo(info.selected.data.extData);
                  });
              }
            });
            // 获取当前定位
            AMap.plugin('AMap.Geolocation', function() {
              var geolocation = new AMap.Geolocation({
                enableHighAccuracy: true, // 是否使用高精度定位,默认:true
                timeout: 10000, // 超过10秒后停止定位,默认:5s
                buttonPosition: 'RB', // 定位按钮的停靠位置
                zoomToAccuracy: false // 定位成功后是否自动调整地图视野到定位点
              });
              _self.map.addControl(geolocation);
              geolocation.getCurrentPosition(function(status, result) {
                if (status == 'complete') {
                  let infoWindow = new AMap.InfoWindow({
                    isCustom: true,
                    content: `<p class="self-position"><strong>${
                      result.formattedAddress
                    }</strong></p>`,
                    offset: new AMap.Pixel(0, -20)
                  });
                  infoWindow.open(_self.map, [
                    result.position.lng,
                    result.position.lat
                  ]);
                  // onComplete(result);
                } else {
                  _self.$Message.error(result);
                }
              });
            });
            // 获取省份编码(标记点所在的省份)
            AMap.plugin('AMap.Geocoder', function() {
              var geocoder = new AMap.Geocoder({
                // city 指定进行编码查询的城市,支持传入城市名、adcode 和 citycode
                // city: '010'
              });
              _self.markers.forEach(item => {
                let lnglat = item.extData.location;
                geocoder.getAddress(lnglat, function(status, result) {
                  if (status === 'complete' && result.regeocode) {
                    var address = result.regeocode.addressComponent;
                    _self.$set(item.extData, 'adcode', address.adcode);
                    _self.$set(item.extData, 'citycode', address.citycode);
                    _self.$set(
                      item.extData,
                      'proecode',
                      item.extData.adcode.substring(0, 2) + '0000'
                    );
                    var formatAddress = result.regeocode.formattedAddress;
                    _self.a_provincecode.push(item.extData.proecode);
                  } else {
                    _self.$Message.error('根据经纬度查询地址失败!');
                    return false;
                    // log.error('根据经纬度查询地址失败');
                  }
                });
              });
            });
            // 多区域加载

            // var adcodes = [370000, 330100, 330200, '0871'];
          }
        );
      });
    });
  },
  methods: {
    async getFactoryStatesAndAbnormalCount() {
      let { data } = await this.$http.get(
        '/outlierquery/v1/outlier/factory/stateAndAbnormalCount',
        {
          params: {
            orgLevel: this.orgLevel,
            uri: this.uri
          }
        }
      );
      if (data.code !== 0) return;
      if (data.result.length == 0) {
        this.$Message.error('暂无水厂数据');
        return;
      }
      this.markers = data.result.map((item, index) => {
        // 0 离线 1 在线
        const Icon =
          item.state == '0' ? NoNet : item.state == '1' ? HasNet : '';
        const POSITION = item.location.split(',');
        let _this = this;
        return {
          extData: item,
          position: POSITION,
          icon: Icon,
          visible: true,
          draggable: false
        };
      });

      let aLng = this.markers.map(item => {
        return parseFloat(item.position[0]);
      });
      let aLat = this.markers.map(item => {
        return parseFloat(item.position[1]);
      });
      let { maxLng, minLng, maxLat, minLat } = {
        maxLng: Math.max(...aLng),
        minLng: Math.min(...aLng),
        maxLat: Math.max(...aLat),
        minLat: Math.min(...aLat)
      };
      this.center = [(maxLng + minLng) / 2, (maxLat + minLat) / 2];
      return { maxLng, minLng, maxLat, minLat };
    },
    routeTo(point) {
      this.$router.push({
        name: 'abnormal_data_count',
        query: {
          factoryUri: point.factoryUri,
          factoryName: point.factoryName,
          orgLevel: 5
        }
      });
    },
    renderAreaNode(areaNode) {
      var colors = ['#dc3912'];
      // 绘制子区域
      this.districtExplorer.renderSubFeatures(areaNode, function(feature, i) {
        var fillColor = colors[i % colors.length];
        var strokeColor = colors[colors.length - 1 - (i % colors.length)];
        return {
          cursor: 'default',
          // bubble: true,
          // strokeColor: strokeColor, // 线颜色
          // strokeOpacity: 0, // 线透明度
          strokeWeight: 0.2 // 线宽
          // fillColor: fillColor, // 填充色
          // fillOpacity: 0.15 // 填充透明度
        };
      });

      // 绘制父区域
      this.districtExplorer.renderParentFeature(areaNode, {
        zIndex: 12,
        cursor: 'default',
        bubble: true,
        strokeColor: '#333', // 线颜色
        strokeOpacity: 1, // 线透明度
        strokeWeight: 0.2, // 线宽
        fillColor: null, // 填充色
        fillOpacity: 0.35 // 填充透明度
      });
    }
  },
  watch: {
    map: function() {
      if (this.map) {
        this.map.setFitView([new AMap.Polyline({ path: this.markers })]);
      }
    },
    a_provincecode: function() {
      let _self = this;
      if (
        this.a_provincecode &&
        this.districtExplorer &&
        this.a_provincecode.length === this.markers.length
      ) {
        this.districtExplorer.loadMultiAreaNodes(this.a_provincecode, function(
          error,
          areaNodes
        ) {
          if (error) {
            _self.$Message.error(error);
            return false;
          }
          // 清除已有的绘制内容
          _self.districtExplorer.clearFeaturePolygons();

          for (var i = 0, len = areaNodes.length; i < len; i++) {
            _self.renderAreaNode(areaNodes[i]);
          }
          // 更新地图视野
          // _self.map.setFitView(districtExplorer.getAllFeaturePolygons());
        });
      }
    }
  }
};
</script>
<style lang="less">
#uimap {
  min-height: 1260px;
}
.infoTitle {
  padding: 0 10px;
  height: 32px;
  line-height: 32px;
}
.infoWindow {
  min-width: 200px;
  height: 32px;
  line-height: 32px;
  padding: 0 10px;
  .right {
    float: right;
  }
}
.self-position {
  background-color: #fff;
  padding: 10px;
  border: 1px solid #53aeef;
  position: relative;
  top: -5px;
}
</style>
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

VUE中使用高德地图(原生UI,信息窗体内部事件监听) 的相关文章

随机推荐

  • react——组件API

    h1 h1 h1 react组件API h1 p 在本章我们将讨论react组件的API 设置状态 setState 替换状态 replaceState 设置属性 setProps 替换属性 replaceProps 强制更新 forceU
  • 情侣飞行棋 情侣小游戏 2023 抖音

    飞行棋网站地址 https effect guoyaxue top fxq index html 以及各种新版来袭 以及各种情侣小游戏合集 https fxnew guoyaxue top
  • uni.uploadFile遇见的坑uploadFile:fail createUploadTask:fail file not found

    uni uploadFile遇见的坑 这两天用uni uni uploadFile遇见个坑上传图片时候一直报错 uploadFile fail createUploadTask fail file not found 我尝试各种方法都没解决
  • Mysql 左外联查left join及多次联查同一张表时的sql优化调优。

    近期接触了大量用户数据导出业务 因业务生命周期短及需程序少迭代等约束 遂编写大SQL用以导出大量用户数据 初版Sql 为正常的左外联查并对应的对及联条件引入联合索引此为sql优化点 1 针对联查条件引入索引 EXPLAIN SELECT a
  • python pandas中ExcelFile与read_excel的区别

    ExcelFile与read excel是pandas中处理excel文件的两个方法 本文将从实例进行说明 来介绍这两种方法的区别 事实上 尽管预料到pandas同时支持这两种方法 但整体上我还不知道pandas对这两个方法的定位是什么 而
  • postman使用技巧

    文章目录 postman使用技巧 动态获取token 1 使用restful API接口登录设备 2 添加token变量 3 添加token判断 postman使用技巧 动态获取token 1 使用restful API接口登录设备 2 添
  • 毕业设计-基于协同过滤算法的个性化推荐系统

    目录 前言 课题背景和意义 实现技术思路 一 预备知识 二 基于SlopeOne的协同过滤推荐优化算法 三 基于改进 的协同过滤推荐优化算法 四 结论及展望 实现效果图样例 最后 前言 大四是整个大学期间最忙碌的时光 一边要忙着备考或实习为
  • Exception:两个类具有相同的 XML 类型名称,请使用 @XmlType.name 和 @XmlType.namespace 为类分配不同的名称...

    两个类具有相同的 XML 类型名称 http service webservice base xm searchAccountBatchResponse 请使用 XmlType name 和 XmlType namespace 为类分配不同
  • MyBatis choose、when和otherwise标签简介说明

    转自 MyBatis choose when和otherwise标签简介说明 MyBatis 中动态语句 choose when otherwise其功能 同Java中的switch case default语句相同 但是因为MyBatis
  • stata 线性回归分析基本操作

    一 线性回归基本命令 regress y x1 x2 红色表示该命令可简写为红色部分 以 Nerlove 数据为例 数据附后文 regress lntc lnq lnpf lnpk lnpl 表上半部分为方差分析表 包括回归平方和 残差平方
  • python对excel增删改查语句_python对 MySQL 数据库进行增删改查的脚本

    coding utf 8 import pymysql import xlrd import codecs 连接数据库 conn pymysql connect host 127 0 0 1 port 3306 user root pass
  • 不显示头像服务器问题,完美解决Gravatar头像不显示的问题

    最近一段时间 感觉我的博客打开速度很慢 页面总是加载不完 仔细检查发现gravatar头像不显示了 再一搜才知道原来gravatar的头像服务器被那啥了 对于隔三差五出现这种情况 相信各位已经无力吐槽 只能在心里默念一句 祝病魔早日 原博主
  • HarmonyOSd第一次任务

    JS FA 应用的 JS 模块 entry src main js module 的典型开发目录结构如下 目录结构中文件分类如下 hml 结尾的 HML 模板文件 这个文件用来描述当前页面的文件布局结构 css 结尾的 CSS 样式文件 这
  • Centos 磁盘根目录扩容

    Centos磁盘根目录扩容 1 扩容前检查 命令 df Th or df h 我们要扩张磁盘空间的就是挂载点为 的这个 2 添加sda磁盘空间查询磁盘 命令 fdisk l 其实 我们可以将sda的磁盘新增空间分配给处于sda的 挂载目录
  • 折线图横坐标怎么设置_Excel折线图的横坐标如何设置?方法超简单,赶快学起来...

    在我们平时使用Excel表格来进行各种数据的编辑工作时 我们往往会因为某一些实际的需求 需要在表格当中插入一些图表 以此来更加清晰 直观的展现此时表格数据当中的内容 而在Excel表格当中插入折线图 相信这是很多小伙伴都会做的工作 尤其是想
  • TCL变量

    目录 简单变量 数组 相关命令 set unset append和incr 简单变量 一个 TCL 的简单变量包含两个部分 名字和值 名字和值都可以是任意字符串 例如一个名为 1323 7 hdgg 的变量在 TCL 中都是合法的 不过为了
  • SSD,PCI-E,NVMe,M.2分类详解

    SSD PCI E NVMe M 2分类详解 首先说一下目前固态硬盘常用的两个接口 与主板相连的接口形状 SATA3和M 2 1 采用SATA3接口 目前机械硬盘采用的接口方式 的固态硬盘 在传输方式上与SATA3 的机械硬盘一样 速度的提
  • 如何使用Pandas的ExcelWriter进行excel操作

    pandas ExcelWriter定制格式 定制表头 渲染颜色等 非ExcelWriter标准的创建模式 ExcelWriter这个插件有个坑 就是已经设置好的格式是无法更改的 因此 由pandas转成excel的时候 必须将格式清除 尤
  • scanf语句的使用和执行原理

    scanf语句的使用和执行原理 1 如何使用scanf 2 scanf语句的原理 1 如何使用scanf d说明我们现在要读入一个整数了 scanf这个函数会读入一个整数 读到的结果赋值给指定变量 要注意指定变量前面的 scanf d pr
  • VUE中使用高德地图(原生UI,信息窗体内部事件监听)

    VUE中使用高德地图 原生UI 先吐槽一下 本人的环境是基于vue3 0的项目 上一位参与项目的同事使用的事vue amap 因工作需要 另外一位同事去了别的项目 所以这个万恶的项目由本人自己维护 就是再本周新增了需求 根据不用大区的用户进