查看: 71|回复: 1

vue-amap 高德地图标记聚合点,自动设置zoom等级

[复制链接]

4

主题

6

帖子

14

积分

新手上路

Rank: 1

积分
14
发表于 2022-12-12 09:24:23 | 显示全部楼层 |阅读模式
备忘自用
效果


根据坐标点标记点,浮动点展示信息,点击点放大(记得应该是有两个不同版本的高德,一个是点击聚合一个是浮动聚合,有相关属性可以设置开关),根据点的经纬度自动设置zoom等级。
"vue-amap": "^0.5.10"
main.js中加入 安选秘钥相关配置
// 高德地图
import VueAMap from 'vue-amap'
Vue.use(VueAMap)
VueAMap.initAMapApiLoader({
  key: '申请的key',
  plugin: [
    'AMap.Autocomplete', // 输入提示插件
    'AMap.PlaceSearch', // POI搜索插件
    'AMap.Scale', // 右下角缩略图插件 比例尺
    'AMap.OverView', // 地图鹰眼插件
    'AMap.ToolBar', // 地图工具条
    'AMap.Geolocation', // 定位控件,用来获取和展示用户主机所在的经纬度位置
    'AMap.MarkerClusterer',
    'AMap.Geocoder'
  ],
  uiVersion: '1.0',
  v: '1.4.15'
})
Vue.config.productionTip = false
// 开发环境
window._AMapSecurityConfig = {
  securityJsCode: '安全密钥'
}
// 生产环境
// window._AMapSecurityConfig = {
//   serviceHost: `${process.env.VUE_APP_BASE_APIA}_AMapService`
// }js
<template>
  <div style='position: relative'>
    <div style='position: absolute;top:20px;left: 100px;z-index: 7'>
      <el-input style='width:200px' placeholder='请输入产品标识/产品名称' v-model='listQuery.queryKey'></el-input>
      <el-date-picker
        v-model='listQuery.startTime'
        style='margin-left: 10px'
        type='date'
        value-format='yyyy-MM-dd HH:mm:ss'
        placeholder='选择开始日期'>
      </el-date-picker>
      <el-date-picker
        v-model='listQuery.endTime'
        value-format='yyyy-MM-dd HH:mm:ss'
        style='margin-left: 10px'
        type='date'
        placeholder='选择结束日期'>
      </el-date-picker>
      <el-button @click='getList' size='mini' style='margin-left: 10px' type='primary' icon='el-icon-search'>搜索
      </el-button>
      <el-button @click='getRest' size='mini' style='margin-left: 10px' icon='el-icon-refresh'>重置
      </el-button>
    </div>
    <div id='warningMapcontainer' style='height: 840px'></div>
  </div>
</template>

<script>

import { codescanwarnmap, warnrecordmap } from '@/api/tapi'

var map
export default {
  data() {
    return {
      typeList: [],
      pointsList: [],
      listQuery: {
        queryKey: '',
        startTime: '',
        isPage: false,
        endTime: ''
      }
    }
  },
  mounted() {
    this.getList()
  },
  beforeDestroy() {
    map && map.destroy()
  },
  methods: {
    getRest() {
      this.listQuery = {
        queryKey: '',
        startTime: '',
        isPage: false,
        endTime: ''
      }
      this.getList()
    },
    getList() {
      warnrecordmap(this.listQuery).then(res => {
        // this.pointsList = res.data
        if (res.data.length == 0) {
          this.$message.info('暂无数据')
        }
        this.$nextTick(() => {
          this.init(res.data)
        })
      })
    },
    markerClick(e) {
      // 拿到之前赋予的keyid值,将该值传入获取详细信息的函数
    },
    init(mapDataList) {
      var cluster, markers = []
      var map = new AMap.Map('warningMapcontainer', {
        center: [116.403694, 39.914271],
        zoom: 6
      })
      window.AMap.plugin(['AMap.ToolBar', 'AMap.Scale', 'AMap.OverView'], function() {
        map.addControl(new window.AMap.ToolBar())
        map.addControl(new window.AMap.Scale())
      })
      var infoWindow
      let maxLng = 0
      let minLng = 0
      let maxLat = 0
      let minLat = 0
      let firstLng = 0
      let firstLat = 0
      for (var i = 0; i < mapDataList.length; i += 1) {
        const ele = mapDataList
        if (i == mapDataList.length - 1) {
          firstLng = ele.lng || 0
          firstLat = ele.lat || 0
        }
        if (ele.lng > maxLng) {
          maxLng = ele.lng || 0
        }
        minLng = ele.lng || 0
        if (ele.lng < minLng) {
          minLng = ele.lng || 0
        }

        if (ele.lat > maxLat) {
          maxLat = ele.lat || 0
        }
        minLat = ele.lat || 0
        if (ele.lat < minLat) {
          minLat = ele.lat || 0
        }
        const markersArr = new AMap.Marker({
          position: [ele.lng, ele.lat],
          content: '<div style="coLor:#fff;text-align:center;font-size: 14px;line-height:24px;background-color: rgba(204, 16, 0, 0.7); height: 24px; width: 24px; border: 1px solid rgb(204, 16, 0); border-radius: 12px; box-shadow: rgb(255 208 204) 0px 0px 5px">1</div>',
          offset: new AMap.Pixel(-15, -15)
        })

        markersArr.on('mouseover', function openInfo() {
          var info = []

          var position = new window.AMap.LngLat(ele.lng || '0', ele.lat || '0')
          // info.push("<div><div><img style=\"float:left;\" src=\" https://webapi.amap.com/images/autonavi.png \"/></div> ");
          // info.push("<div style=\"padding:0px 0px 0px 4px;\"><b>高德软件</b>");
          // info.push(`${ele.productHandle}`)
          // info.push(`<div>时间:${ele.scanTime}</div>`)
          info.push(`<div class='mapInfoBox'><div class='box_title'>${ele.spuName}-${ele.skuName || ''}</div><div>经销商名称:${ele?.distributorName || ''}</div><div> 产品标识:${ele?.code || ''}</div><div>报警时间:${ele?.warnTime || ''}</div><div>报警地点:${ele?.warnAddress || ''}</div></div>`)
          infoWindow = new window.AMap.InfoWindow({
            content: info.join('<br/>') // 使用默认信息窗体框样式,显示信息内容
          })
          infoWindow.open(map, position)
        })
        markersArr.setExtData({ 'info': ele })
        markers.push(markersArr)

      }
      var nowDiv = document.getElementById('warningMapcontainer')
      var distance = AMap.GeometryUtil.distance([maxLng, maxLat], [minLng, minLat]) //以高德提供的方法来获取两点间的距离
      var nowDivLine = Math.sqrt(nowDiv.clientWidth * nowDiv.clientWidth + nowDiv.clientHeight * nowDiv.clientHeight) //求出地图容器的对角线长度
      var nowScale = distance / nowDivLine//求出覆盖物范围和地图容器的比例
      var nowNum = 16 - Math.ceil(Math.log(nowScale) / Math.log(2))//求出可以显示出所有覆盖物的级别
      var count = markers.length
      var _renderClusterMarker = function(context) {
        var factor = Math.pow(context.count / count, 1 / 18)
        var div = document.createElement('div')
        var Hue = 180 - factor * 180
        var bgColor = 'hsla(' + Hue + ',100%,40%,0.7)'
        var fontColor = 'hsla(' + Hue + ',100%,90%,1)'
        var borderColor = 'hsla(' + Hue + ',100%,40%,1)'
        var shadowColor = 'hsla(' + Hue + ',100%,90%,1)'
        div.style.backgroundColor = bgColor
        var size = Math.round(30 + Math.pow(context.count / count, 1 / 5) * 20)
        div.style.width = div.style.height = size + 'px'
        div.style.border = 'solid 1px ' + borderColor
        div.style.borderRadius = size / 2 + 'px'
        div.style.boxShadow = '0 0 5px ' + shadowColor
        div.innerHTML = context.count
        div.style.lineHeight = size + 'px'
        div.style.color = fontColor
        div.style.fontSize = '14px'
        div.style.textAlign = 'center'
        context.marker.on('click', function(e) {
          const value = e.target.getExtData()
        })
        context.marker.on('mouseover', function(e) {
          setTimeout(() => {
            var info = []
            var position = new window.AMap.LngLat(e.lnglat.lng, e.lnglat.lat)
            context.markers.forEach(ele => {
              info.push(`<div class='mapInfoBox'><div class='box_title'>${ele.De.extData.info.spuName}-${ele.De.extData.info.skuName}</div><div>经销商名称:${ele.De.extData.info?.distributorName || ''}</div><div> 产品标识:${ele.De.extData.info?.code || ''}</div><div>报警时间:${ele.De.extData.info?.warnTime || ''}</div><div>报警地点:${ele.De.extData.info?.warnAddress || ''}</div></div>`)
            })
            infoWindow = new window.AMap.InfoWindow({
              // content: info.join('<br/>')  // 使用默认信息窗体框样式,显示信息内容
              content: info.join('<span></span>')  // 使用默认信息窗体框样式,显示信息内容

            })
            infoWindow.open(map, position)
          }, 100)
        })
        context.marker.on('mouseout', function(e) {
          // setTimeout(() => {
          //   infoWindow && infoWindow.close()
          // }, 100)
        })
        context.marker.setOffset(new AMap.Pixel(-size / 2, -size / 2))
        context.marker.setContent(div)
      }
      addCluster(2)

      function addCluster(tag) {
        if (cluster) {
          cluster.setMap(null)
        }
        if (tag == 2) {//完全自定义
          cluster = new AMap.MarkerClusterer(map, markers, {
            gridSize: 80,
            renderClusterMarker: _renderClusterMarker
          })
        } else if (tag == 1) {//自定义图标
          var sts = [{
            url: 'https://a.amap.com/jsapi_demos/static/images/blue.png',
            size: new AMap.Size(32, 32),
            offset: new AMap.Pixel(-16, -16)
          }, {
            url: 'https://a.amap.com/jsapi_demos/static/images/green.png',
            size: new AMap.Size(32, 32),
            offset: new AMap.Pixel(-16, -16)
          }, {
            url: 'https://a.amap.com/jsapi_demos/static/images/orange.png',
            size: new AMap.Size(36, 36),
            offset: new AMap.Pixel(-18, -18)
          }, {
            url: 'https://a.amap.com/jsapi_demos/static/images/red.png',
            size: new AMap.Size(48, 48),
            offset: new AMap.Pixel(-24, -24)
          }, {
            url: 'https://a.amap.com/jsapi_demos/static/images/darkRed.png',
            size: new AMap.Size(48, 48),
            offset: new AMap.Pixel(-24, -24)
          }]
          cluster = new AMap.MarkerClusterer(map, markers, {
            styles: sts,
            gridSize: 80
          })
        } else {//默认样式
          cluster = new AMap.MarkerClusterer(map, markers, { gridSize: 80 })
        }
      }

      map.setFitView()
      if (mapDataList.length != 0) {
        map.setZoom(distance == 0 || nowNum === Infinity ? 18 : nowNum - 1)
      } else {
        map.setZoom(14)
      }
      if (distance == 0 && mapDataList.length != 0) {
        map.setCenter([maxLng, maxLat])
      }
      if (distance != 0 && mapDataList.length != 0) {
        map.setCenter([firstLng, firstLat])
      }
      map.on('click', function() {
        infoWindow && infoWindow.close()
      })
    }
  }
}
</script>
<style lang='scss'>
.mapInfoBox {
  background: #F6F6F6;
  border-radius: 10px;
  padding: 10px;
  margin: 10px;
  width: 360px;

  .box_title {
    margin-bottom: 4px;
    font-size: 16px;
    font-weight: bold;
  }


}

.amap-info-close {
  right: 8px !important;
}

/*html, body {*/
/*  margin: 0;*/
/*  height: 100%;*/
/*  width: 100%;*/
/*  position: absolute;*/
/*}*/

#container {
  position: absolute;
  top: 100%;
  left: -10%;
  right: 0%;
  bottom: 100%;
  width: 500%;
  height: 500%;
}

.button-group {
  position: absolute;
  bottom: 20px;
  right: 20px;
  font-size: 12px;
  padding: 10px;
}

.button-group .button {
  height: 28px;
  line-height: 28px;
  background-color: #0D9BF2;
  color: #FFF;
  border: 0;
  outline: none;
  padding-left: 5px;
  padding-right: 5px;
  border-radius: 3px;
  margin-bottom: 4px;
  cursor: pointer;
}

.button-group .inputtext {
  height: 26px;
  line-height: 26px;
  border: 1px;
  outline: none;
  padding-left: 5px;
  padding-right: 5px;
  border-radius: 3px;
  margin-bottom: 4px;
  cursor: pointer;
}

/*
.tip {
   position: absolute;
   bottom: 30px;
   right: 10px;

   text-align: center;
   border: 1px solid #ccc;
   line-height: 30px;
   border-radius: 3px;
   padding: 0 5px;
   font-size: 12px;
}
*/
#tip {
  background-color: #fff;
  padding-left: 10px;
  padding-right: 10px;
  position: absolute;
  font-size: 12px;
  right: 10px;
  top: 20px;
  border-radius: 3px;
  border: 1px solid #ccc;
  line-height: 30px;
}

/*
#tip input[type='button'] {
    margin-top: 10px;
    margin-bottom: 10px;

    height: 30px;
    text-align: center;
    line-height: 30px;
    color: #fff;
    font-size: 12px;
    border-radius: 3px;
    outline: none;
    border: 0;
}
*/
.amap-info-content {
  font-size: 12px;
  padding-right: 5px;

  &::-webkit-scrollbar-thumb {
    background: #e2e3e8;
    border-radius: 5px;
    cursor: pointer;
  }

  &::-webkit-scrollbar {
    width: 7px;
    height: 7px;
  }
}

#myPageTop {
  position: absolute;
  top: 5px;
  right: 10px;
  background: #fff none repeat scroll 0 0;
  border: 1px solid #ccc;
  margin: 10px auto;
  padding: 6px;
  font-family: "Microsoft Yahei", "微软雅黑", "Pinghei";
  font-size: 14px;
}

#myPageTop label {
  margin: 0 20px 0 0;
  color: #666666;
  font-weight: normal;
}

#myPageTop input {
  width: 170px;
}

#myPageTop .column2 {
  padding-left: 25px;
}

.amap-info-content {
  max-height: 360px;
}
</style>
回复

使用道具 举报

2

主题

8

帖子

15

积分

新手上路

Rank: 1

积分
15
发表于 前天 22:37 | 显示全部楼层
传说中的沙发???哇卡卡
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表