SOURCE

console 命令行工具 X clear

                    
>
console
function loadMap (key, plugins, v = '1.4.14') {
  return new Promise(function (resolve, reject) {
    if (typeof AMap !== 'undefined') {
      // eslint-disable-next-line no-undef
      resolve(AMap)
      return true
    }
    window.onCallback = function () {
      // eslint-disable-next-line no-undef
      resolve(AMap)
    }
    let script = document.createElement('script')
    script.type = 'text/javascript'
    script.src = `https://webapi.amap.com/maps?v=${v}&key=${key}&plugin=${plugins}&callback=onCallback`
    script.onerror = reject
    document.head.appendChild(script)
  })
}
var Main = {
    data () {
    return {
      // 地图实例
      GDMap: null,
      // 加载的一些插件
      // 更多参考:https://lbs.amap.com/api/javascript-api/guide/abc/plugins#plugins
      plugins: [
        'AMap.OverView',
        'AMap.MouseTool',
        'AMap.PolyEditor',
        'AMap.RectangleEditor',
        'AMap.PlaceSearch',
        'AMap.DistrictLayer',
        'AMap.CustomLayer'
      ],
      // key
      key: 'c5eac55551560531336988396dacbf53',
      // 地图版本
      v: '1.4.14',
      loading: true,
      // 多边形集合
      polygons: [
        [
          [ 116.402921, 39.984507 ],
          [ 116.531324, 39.938719 ],
          [ 116.525144, 39.858648 ],
          [ 116.423521, 39.821742 ]
        ]
      ],
      polygonsGroup: null, // 多边形OverlayGroup集合实例,方便管理
      isDrawing: false, // 是否正在绘制
      drawingPolygon: {
        polyline: null, // 绘制过程中的折线实例
        polylinePath: [], // 折线的path
        polygon: null, // 根据折线路径自动生成的多边形的实例
        pointsGroup: null, // 绘制过程中点的集合的实例
        pointOnLine: null, // 多边形边上的点的实例
        isOnPolygon: null // 点是否在多边形上
      },
      styles: {
        // 圆点option
        circleMarker: {
          radius: 4,
          strokeColor: '#010301',
          strokeWeight: 2,
          strokeOpacity: 1,
          fillColor: '#FFFFFF',
          fillOpacity: 1,
          bubble: true,
          cursor: 'pointer',
          clickable: true,
          zIndex: 999999
        },
        // 绘制过程中折线的option
        drawingPolyline: {
          strokeColor: '#dd9ab0',
          strokeWeight: 5,
          strokeStyle: 'dashed',
          strokeDasharray: [5, 20],
          bubble: true
        },
        polygon: {
          fillColor: '#DC3021', // 填充色
          fillOpacity: 0.2, // 填充透明度
          strokeColor: '#DC3021', // 轮廓颜色
          strokeWeight: 1, // 轮廓宽度
          strokeOpacity: 0.9 // 轮廓透明度
        }
      }
    }
  },
  mounted () {
    loadMap(this.key, this.plugins, this.v)
      .then(AMap => {
        this.GDMap = new AMap.Map('GDMap', {
          zoom: 11,
          center: [116.397428, 39.90923],
          isHotspot: false
        })
        // 绑定地图单击事件
        this.GDMap.on('click', this.mapOnClick)
        // 地图双击事件
        this.GDMap.on('dblclick', this.mapOnDblclick)
        // 绑定地图鼠标移动事件
        this.GDMap.on('mousemove', this.mapOnMouseMove)

        this.GDMap.on('complete', () => {
          // 地图加载完成后初始化已有的多边形
          this.polygons.forEach(polygon => {
            this.addPolygon(polygon)
          })
        })
      })
      .catch(() => {
        console.log('地图加载失败!')
      })
  },
  methods: {
    drawPolygon () {
      this.isDrawing = true
    },
    // 地图点击事件
    mapOnClick (ev) {
      if (!this.isDrawing) return
      let position = [ev.lnglat.lng, ev.lnglat.lat] // 鼠标点击的坐标
      // 判断是否存在存在线上圆点实例及是否在线上
      if (this.drawingPolygon.isOnPolygon && this.drawingPolygon.pointOnLine) {
        const center = this.drawingPolygon.pointOnLine.getCenter() // 获取线上圆点的中心
        position = [center.lng, center.lat]
      }
      this.addPolygonPoint(position) // 地图上增加相应的点
      this.addDrawingPolyline([position, position]) // 添加绘制过程中的鼠标移动位置的折线
      this.drawPolygonByPoints() // 通过点围成多边形
    },
    // 地图双击事件
    mapOnDblclick (ev) {
      if (!this.isDrawing) return
      this.complateDraw()
    },
    // 地图鼠标移动事件
    mapOnMouseMove (ev) {
      if (!this.isDrawing) return
      const position = [ev.lnglat.lng, ev.lnglat.lat]
      const linePath = this.getPointLine(position) // 获取点所在的线
      let recentPoint = null // 定义最近的点
      if (this.drawingPolygon.isOnPolygon) {
        // 如果点在线上(这个点存在偏移,所以还得通过getRecentPoint获取到正在的最近的一个点)
        // 获取该点到线的最近的一个点
        recentPoint = this.getRecentPoint(linePath, position)
        this.addDrawingOnLinePoint(recentPoint) // 在线上添加圆点,也就是自动吸附的时候创建的点
      } else {
        this.removeDrawingOnLinePoint()
      }
      this.setDrawingPolyline(position)
    },
    // 添加围成多边形的点
    addPolygonPoint (position) {
      // 样式及坐标option
      const option = {
        ...this.styles.circleMarker,
        center: position
      }
      const circlePointMarker = new AMap.CircleMarker(option) // 单个圆点实例
      // 先判断是否存在圆点集合实例
      // 所有的圆点这里通过高德提供的OverlayGroup统一管理
      if (!this.drawingPolygon.pointsGroup) { // 如果不存在
        this.drawingPolygon.pointsGroup = new AMap.OverlayGroup() // 创建绘制过程中点的集合的实例
        this.GDMap.add(this.drawingPolygon.pointsGroup) // 将集合添加到地图上显示
      }
      this.drawingPolygon.pointsGroup.addOverlay(circlePointMarker) // 将点添加到集合里面
    },
    // 新增绘制中的折线
    addDrawingPolyline (paths) {
      // 判断有无折线
      if (this.drawingPolygon.polyline) {
        this.drawingPolygon.polyline.setPath(paths) // 有的话直接设置折线路径
      } else { // 没有的话需要创建折线
        // 折线样式及路径
        const option = {
          ...this.styles.drawingPolyline,
          path: paths
        }
        this.drawingPolygon.polyline = new AMap.Polyline(option) // 生成折线
        this.GDMap.add(this.drawingPolygon.polyline) // 地图上添加折线
      }
      this.drawingPolygon.polylinePath = paths // 存一下折线的路径
    },
    // 设置绘制中的折线的路径
    setDrawingPolyline (position) {
      if (this.drawingPolygon.polyline) {
        // 新增的折线的路径,由上次记录折线的开始点+鼠标坐标位置点
        const linePath = [
          this.drawingPolygon.polylinePath[0], // 上次记录折线的开始点
          position // 鼠标坐标位置点
        ]
        this.drawingPolygon.polyline.setPath(linePath)
        this.drawingPolygon.polylinePath = linePath
      }
    },
    // 根据点画区块多边形
    drawPolygonByPoints () {
      const pointsGroup = this.drawingPolygon.pointsGroup // 点及的集合实例
      const pointsLength = pointsGroup ? pointsGroup.getOverlays().length : 0 // 点的长度
      if (pointsLength > 1) {
        // 获取每个点的中心点组成path
        const paths = pointsGroup.getOverlays().map(item => {
          const path = item.getCenter()
          return [path.lng, path.lat]
        })
        // 地图上绘制多边形
        if (this.drawingPolygon.polygon) {
          this.drawingPolygon.polygon.setPath(paths)
        } else {
          const option = {
            ...this.styles.polygon,
            path: paths
          }
          this.drawingPolygon.polygon = new AMap.Polygon(option)
          this.drawingPolygon.polygon.setMap(this.GDMap)
        }
      }
    },
    // 绘制完成
    complateDraw () {
      const paths = this.drawingPolygon.polygon.getPath().map(item => [item.lng, item.lat]) // 绘制完成的多边形path
      this.isDrawing = false // 取消绘制
      this.polygons.push(paths) // 添加绘制的多边形
      this.addPolygon(paths) // 地图上添加绘制的多边形
      this.clearUselessOverlays() // 清理数据
    },
    // 清理无用的图层
    clearUselessOverlays () {
      if (!this.GDMap) return
      this.GDMap.remove(this.drawingPolygon.polyline)
      this.GDMap.remove(this.drawingPolygon.polygon)
      this.GDMap.remove(this.drawingPolygon.pointsGroup)
      if (this.drawingPolygon.pointOnLine) {
        this.GDMap.remove(this.drawingPolygon.pointOnLine)
      }
      this.drawingPolygon.polyline = null
      this.drawingPolygon.polygon = null
      this.drawingPolygon.pointsGroup = null
      this.drawingPolygon.polylinePath = []
      this.drawingPolygon.isOnPolygon = false
    },
    // 添加多边形
    addPolygon (paths) {
      if (!this.GDMap) return
      const option = {
        ...this.styles.polygon,
        path: [...paths]
      }
      const polygon = new AMap.Polygon(option)
      if (!this.polygonsGroup) {
        this.polygonsGroup = new AMap.OverlayGroup()
        this.GDMap.add(this.polygonsGroup)
      }
      this.polygonsGroup.addOverlay(polygon)
    },
    // 添加多边形边线上的点
    addDrawingOnLinePoint (center) {
      if (this.drawingPolygon.pointOnLine) {
        this.drawingPolygon.pointOnLine.setCenter(center)
        return
      }
      const option = {
        map: this.GDMap,
        center: center,
        ...this.styles.circleMarker
      }
      this.drawingPolygon.pointOnLine = new AMap.CircleMarker(option)
    },
    // 移除多边形线上的点
    removeDrawingOnLinePoint () {
      if (this.drawingPolygon.pointOnLine) {
        this.GDMap.remove(this.drawingPolygon.pointOnLine)
        this.drawingPolygon.pointOnLine = null
      }
    },
    // 获取点所在的线
    getPointLine (position) {
      const resolution = this.GDMap.getResolution()// 获取指定位置的地图分辨率,单位:米/像素
      const pointWidth = 6 * resolution// 线段上圆点的宽度,也就是误差
      let linePath = []
      this.drawingPolygon.isOnPolygon = false // 默认点不在线上
      // 循环所有的多边形,取到所有的线一一比较,存在性能问题
      for (let i = 0; i < this.polygons.length; i++) {
        const itemPath = this.polygons[i]
        let hasFind = false
        for (let n = 0; n < itemPath.length; n++) {
          const path = itemPath[n]
          const nextPath = itemPath[n + 1]
          const line = nextPath ? [path, nextPath] : [path, itemPath[0]]
          // 高德地图提供的isPointOnSegment判断点是否在线段上
          const isPointOnSegment = AMap.GeometryUtil.isPointOnSegment(position, line[0], line[1], pointWidth)
          if (isPointOnSegment) {
            linePath = line
            this.drawingPolygon.isOnPolygon = true
            hasFind = true
            break
          }
        }
        if (hasFind) break
      }
      return linePath
    },
    // 获取最近的点的坐标
    getRecentPoint (paths, curPointPosition) {
      const recentPoint = AMap.GeometryUtil.closestOnLine(curPointPosition, paths)
      return recentPoint
    }

  },
  watch: {
    isDrawing (newState) {
      if (newState) {
        this.GDMap.setDefaultCursor('crosshair')
      } else {
        this.GDMap.setDefaultCursor('')
      }
      this.GDMap.setStatus({
        doubleClickZoom: !newState
      })
    }
  }
  }
var Ctor = Vue.extend(Main)
new Ctor().$mount('#app')
<script src="https://unpkg.com/vue@2.6.10/dist/vue.js">
</script>
<div id="app">
  <template>
    <div class="map">
      <button type="primary" @click="drawPolygon">
        画多边形
      </button>
      <div id="GDMap">
      </div>
    </div>
  </template>
</div>
#GDMap {
  width: 1200px;
  height: 500px;
  position: relative;
}