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

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>
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值