离线高德地图

最近公司需要内网开发,使用到高德地图,正好碰到,在这里记录一下。本博客中实现了离线高德地图显示,点聚合,非聚合点自定义图标,图标点击弹出信息框,框选,圈选区域这些功能。

效果图:

实现思路:

1、下载地图瓦片数据,gitee有个开源地图瓦片下载项目,我fork了一下,地图下载器

如果有fork失败的兄弟,可以找我私信要。

2、下载高德地图离线2.0JS API,高德地图离线地图api地址

amap文件夹放在public下边,和瓦片数据同一级。

声明

  • 本离线包基于高德地图js-api2.0,在此基础进行修改。
  • 本项目仅为个人兴趣开发,不收费,作者也不提供任何付费服务。
  • 本项目仅供个人学习研究使用。
  • 本项目禁止商用,禁止在企业项目开发中使用此地图离线包,禁止使用此离线包以及基于此项目二次开发的软件从事盈利活动。

3、第一步和第二步已经能实现简单的高德地图渲染了,但是我们加载地图肯定是需要别的操作,比如点聚合,非聚合点自定义图标,图标点击弹出信息框,框选,圈选区域这些功能。这时候就需要我们我们自带的AMap3.js可能没有或者对应的插件包报错,我们就应该添加新的插件对应的js。

下载方法,本地项目中引入在线的高德地图,plugins中把我们需要的插件添加进去。

然后运行起来,在网页端network中下载对应的js,然后查找关键字_jsload_,把我们新添加插件对应的这一串添加到我们本地AMap3.js的最下边就OK了。

基本步骤就说清楚了,下边是一些显示,点聚合,非聚合点自定义图标,图标点击弹出信息框的代码。

    //初始化
    async initData() {
      //定义地图
      const base_url = "../../";
      const layers = [new AMap.TileLayer({
        getTileUrl: function (x, y, z) {
          return `${base_url}MAP_zxy/${z}/${x}/${y}.png`;
        },
        opacity: 1,
        zIndex: 99,
      })]
      this.map = new AMap.Map('container', { // 设置地图容器id
        zoom: 10,
        resizeEnable: true,
        rotateEnable: true,
        pitchEnable: true,
        // center: [104.96824,33.375687],
        center: [103.847998, 36.067468],
        defaultCursor: 'pointer',
        showLabel: true,  //是否显示文字标注
        layers: layers
      })

      //聚合打点
      this.addCluster();

      //定义鼠标框选工具
      this.mouseTool = new AMap.MouseTool(this.map);
      const that = this;
      this.mouseTool.on('draw', function (event) {
        that.markerForFigure = [];
        that.mouseTool.close(false);

        // 获取所有点
        var allMarkers = that.map.getAllOverlays('marker');
        var eObject = event.obj;//obj覆盖物对象。
        allMarkers.forEach((marker => {
          var markerInPolygon = eObject.contains(marker.getPosition());//是否包含marker
          if (markerInPolygon) {
            that.markerForFigure.push(marker)
          }
        }));
        console.log(that.markerForFigure, "被选中的标记")
      });
    },

    addCluster() {
      let pointers = [];
      if (this.rawData) {
        this.rawData.map((value, index) => {
          if (value.longitude !== undefined && value.latitude !== undefined) {
            pointers.push({
              weight: 1,
              lnglat: [
                this.toFixedDigit(value.longitude - 0, 5),
                this.toFixedDigit(value.latitude - 0, 5),
              ],
              deviceId: value.deviceId,
              deviceCode: value.channelId,
              deviceName: value.channelName,
              orgCode: value.orgCode,
              isOnline: value.psOnlineState,
              manufacture: value.manufacture,
            });
            this.allPointers = pointers;
          }
        });
      }
      if (this.cluster && this.cluster != null) { //1. 如果存在 cluster 说明已经初始化过了,直接使用,变更它的点的内容就可以了。
        this.cluster.setData(pointers);
      } else {//2. 如果没有 cluster 就进行初始化。
        this.infoWindow = new AMap.InfoWindow({ closeWhenClickMap: true, offset: new AMap.Pixel(0, -30) });
        this.cluster = new AMap.MarkerCluster(
          this.map, // 地图实例
          pointers, // 海量点数据,数据中需包含经纬度信息字段 lnglat
          {
            gridSize: 60,// 设置网格像素大小
            // renderClusterMarker: this.renderClusterMarker, // 自定义聚合点样式
            renderMarker: this.renderMarker, // 自定义非聚合点样式
          }
        )
      }
      this.cluster.on('click', (item) => {
        //此处是通过包含点的数量判断是否是聚合点,不是聚合点就执行上方单个点的点击方式
        if (item.clusterData.length <= 1) {
          return;
        }
        //这里是计算所有聚合点的中心点
        let alllng = 0, alllat = 0;
        for (const mo of item.clusterData) {
          alllng += mo.lnglat.lng;
          alllat += mo.lnglat.lat;
        }
        const lat = alllat / item.clusterData.length;
        const lng = alllng / item.clusterData.length;
        //这里是放大地图,此处写死了每次点击放大的级别,可以根据点的数量和当前大小适应放大,体验更佳
        this.map.setZoomAndCenter(this.map.getZoom() + 4, [lng, lat]);
      });
    },
    //格式化经纬度
    toFixedDigit(num, n) {
      //保留n位
      if (typeof num != "number") {
        return false;
      }

      num = num.toString();
      var result = "";
      var zeroResult = function (n) {
        var zero = "";
        for (var i = 0; i < n; i++) {
          zero += "0";
        }
        return zero;
      };
      if (num % 1 == 0) {
        //整数
        result = num + "." + zeroResult(n);
      } else {
        //小数
        var num1 = num.split(".");
        if (num1[1].length < n) {
          result = num1[0] + "." + num1[1] + zeroResult(n - num1[1].length);
        } else {
          result = num1[0] + "." + num1[1].substring(0, n);
        }
      }
      return result;
    },
    //自定义非聚合点样式
    renderMarker(context) {
      const { marker, data } = context;
      let iconOn = new AMap.Icon({
        size: new AMap.Size(66, 80), // 图标尺寸
        image: require(`../../assets/images/video-online.png`), // Icon的图像
        imageSize: new AMap.Size(38, 50), // 根据所设置的大小拉伸或压缩图片
      });
      let iconOff = new AMap.Icon({
        size: new AMap.Size(66, 80), // 图标尺寸
        image: require(`../../assets/images/video-offline.png`), // Icon的图像
        imageSize: new AMap.Size(38, 50), // 根据所设置的大小拉伸或压缩图片
      });
      if (data[0].isOnline == '1') {
        marker.setIcon(iconOn)
      } else if (data[0].isOnline == '0') {
        marker.setIcon(iconOff)
      }
      marker.on("click", (e) => {
        this.singleData = [];
        console.log(this.$refs.infoWindow);
        this.allPointers.forEach(item => {
          if (item.deviceId == data[0].deviceId) {
            this.singleData.push(item)
          }
        })
        console.log(this.singleData);
        this.$nextTick(()=>{
           this.openInfoWindow(e)
        })
       
      });
    },
    openInfoWindow(e) {
      this.infoWindow = new AMap.InfoWindow({
        isCustom: true,
        autoMove: true,
        avoid: [20, 20, 20, 20],
        content: this.$refs.infoWindow,
        closeWhenClickMap: true,
        offset: new AMap.Pixel(16, -40)
      })
      this.infoWindow.open(this.map, e.target.getPosition())
    },
    // 线段
    drawPolyline() {
      this.mouseTool.polyline({
        strokeColor: "#3366FF",
        strokeOpacity: 1,
        strokeWeight: 6,
        // 线样式还支持 'dashed'
        strokeStyle: "solid",
        // strokeStyle是dashed时有效
        // strokeDasharray: [10, 5],
      })
    },
    // 多边形
    drawPolygon() {
      this.mouseTool.close(true)
      this.mouseTool.polygon({
        strokeColor: "#FF33FF",
        strokeOpacity: 1,
        strokeWeight: 6,
        // strokeOpacity: 0.2,
        fillColor: '#1791fc',
        fillOpacity: 0.4,
        // 线样式还支持 'dashed'
        strokeStyle: "solid",
        // strokeStyle是dashed时有效
        // strokeDasharray: [30,10],
      })
    },
    // 矩形
    drawRectangle() {
      this.mouseTool.close(true)
      this.mouseTool.rectangle({
        strokeColor: 'red',
        strokeOpacity: 0.5,
        strokeWeight: 6,
        fillColor: 'blue',
        fillOpacity: 0.5,
        // strokeStyle还支持 solid
        strokeStyle: 'solid',
        // strokeDasharray: [30,10],
      })
    },

评论 20
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值