最全vue的vue-amap使用高德地图插件画多边形范围

一、在vue-cli的框架下的main.js(或者main.ts)中引入高德插件,代码如下:

import Vue from 'vue'
import VueAMap from 'vue-amap'
import ElementUI from 'element-ui'

import App from './App.vue'
import router from './router'
import store from './store'
import './registerServiceWorker'

Vue.use(VueAMap)
Vue.use(ElementUI)

VueAMap.initAMapApiLoader({
  // 高德的key
  key: '你的高德key',
  // 插件集合
  plugin: [
    'AMap.Autocomplete',
    'AMap.PlaceSearch',
    'AMap.Scale',
    'AMap.OverView',
    'AMap.ToolBar',
    'AMap.MapType',
    'AMap.PolyEditor',
    'AMap.CircleEditor',
    'AMap.Geocoder',
    'AMap.Geolocation'
  ],
  // 高德 sdk 版本,默认为 1.4.4
  v: '1.4.10'
})

Vue.config.productionTip = false

new Vue({
  router,
  store,
  render: h => h(App)
}).$mount('#app')

第三种画多边形的效果图:

    注意:1、这种画多边形,开始就需要一个初始的多边形;

       2、所以,输入要画多边形范围的地名,点击搜索,地图会跳转到搜索的地方,同时得到经纬度;

       3、点“范围绘制”时,我再方法里根据第2步的经纬度,初始了一个多边形;

    ****隐藏彩蛋****

  下图的 “请输入经纬度” 可以输入一大组的经纬度,按回车键,也可以画出多边形,在按“范围绘制”也可以更改;(格式如下:)

 

这个格式就是复制的地图上显示的经纬度坐标
106.2246 , 29.59258 106.225064 , 29.593287 106.226137 , 29.593558 106.22692 , 29.593083

 

 

二、第一种画化:使用Geolocation画多边形(效果是在地图点了,才会形成多边形)

// 新增 编辑 查看 
<template>
  <div class="point">
    <el-header></el-header>
    <div class="action-bar">
      <el-form class="inline-form" :rules="rules" ref="formData" size="small" :model="formData">
        <el-form-item label label-width="220" prop="location">
          <el-input
            :disabled="!ifFalg"
            class="name-input"
            clearable
            v-model="formData.location"
            placeholder="名称"
            maxlength="30"
          ></el-input>
        </el-form-item>
        <el-form-item label prop="longitude">
          <el-input
            :disabled="!ifFalg"
            class="my-input"
            clearable
            v-model.number="formData.longitude"
            placeholder="经度 "
          ></el-input>
        </el-form-item>
        <el-form-item label  prop="latitude">
          <el-input
            :disabled="!ifFalg"
            class="my-input"
            clearable
            v-model.number="formData.latitude"
            placeholder="纬度"
          ></el-input>
        </el-form-item>
        <el-button class="my-button" v-if="ifFalg" type="primary" @click="save" size="small">保存</el-button>
        <el-button class="my-button" size="small" @click="close">关闭</el-button>
      </el-form>
    </div>
    <div class="map-box">
      <div class="map-tool">
        <div v-if="ifFalg">
          <el-checkbox v-model="enterType">地图上描点</el-checkbox>
        </div>
        <!-- <el-checkbox @change="checkbox" v-model="enterType">地图上描点</el-checkbox> -->
        <div class="longlat">
          <ul>
            <li v-for="(item, index) in lnglatpoints" :key="index">
              {{item.longitude}} , {{item.latitude}}
              <i
                v-if="ifFalg"
                class="el-icon-close"
                @click="deletes(item)"
              ></i>
            </li>
          </ul>
          <el-input
            v-if="ifFalg"
            class="my-input"
            size="small"
            clearable
            v-model="lngLat"
            @keyup.enter.native="submitEnter"
            placeholder="请输入经纬度"
          ></el-input>
          <el-button v-if="ifFalg" size="small" @click="clear" type="primary" class="claer">清除</el-button>
        </div>
      </div>
      <div class="map" id="map">
        <el-amap
          ref="map"
          bubble
          :plugin="plugin"
          :zoom="map.zoom"
          :center="map.center"
          :events="events"
          id="amap"
        >
          <el-amap-polygon
            :events="plugin.events"
            :path="path"
            :draggable="draggable"
            fillColor="#2b83f9"
            fillOpacity="0.5"
            strokeWeight="0"
            strokeColor="#2b83f9"
            strokeOpacity="0.5"
          ></el-amap-polygon>
          <!-- <el-amap-marker  :position="marker.position" :events="plugin.events"></el-amap-marker> -->
          <el-amap-marker v-if="formData.type === 1" :position="map.center" :label="label"></el-amap-marker>
        </el-amap>
      </div>
     
    </div>
  </div>
</template>
<script lang="ts">
import * as api from '@/utils/api/index'
import { Component, Vue } from 'vue-property-decorator'
import eHeader from '@/components/header.vue'
import { constants } from 'http2'
import * as util from '@/utils/util.ts'

const testLongitude = (rule: any, value: string, callback: Function) => {
  if (util.regExp.longitudeRegExp.test(value)) {
    return callback()
  } else {
    return callback(new Error('请输入正确的经度'))
  }
}
const testLatitude = (rule: any, value: string, callback: Function) => {
  if (util.regExp.latitudeRegExp.test(value)) {
    return callback()
  } else {
    return callback(new Error('请输入正确的纬度'))
  }
}
@Component({
  components: {
    'el-header': eHeader
  }
})
export default class point extends Vue {
  private breadcrumbId = 0
  private id = ''
  private lngLat = ''
  private ifFalg = true
  private map = {
    zoom: 15,
    center: [106.55073, 29.56471]
  }
  private path: any = []
  private draggable = false
  private lnglatpoints: any = []
  private enterType = false // 录入坐标 | 地图上描点
  private cities = []
  private formData = {
    location: '',
    longitude: '',
    latitude: ''
  }
  plugin = {
    pName: 'Geolocation',
    events: {}
  }
  events = {}
  private test = 1

  private rules = {
    location: [
      { required: true, message: '请输入接送点名称', trigger: 'blur' }
    ],
    longitude: [{ validator: testLongitude, trigger: 'blur' }],
    latitude: [{ validator: testLatitude, trigger: 'blur' }]
  }

  mounted() {
    this.id = this.$route.params.id
    this.breadcrumbId = Number(this.$route.query.breadcrumbId)
    if (this.breadcrumbId === 2) {
      this.ifFalg = false
    }
    if (this.id !== '-1') {
      this.details()
    }

    // this.city()
    let _this: any = this

    // 地图点击事件
    _this.events = {
      click: (e: any) => {
        if (this.enterType) {
          this.path = []
          console.log(e.lnglat)
          let lnglat = e.lnglat
          this.lnglatpoints.push({
            latitude: lnglat.lat,
            longitude: lnglat.lng
          })
          console.log(this.lnglatpoints)
          this.lnglatpoints.map((val: any, index: number) => {
            console.log(index)
            if (index === 0) {
              this.map.center = [val.longitude, val.latitude]
            }
            let arr = [val.longitude, val.latitude]
            this.path.push(arr)
          })
          // this.setFitView()
        }
      }
    }

    // 多边形点击事件
    _this.plugin.events = {
      click: (e: any) => {
        if (this.enterType) {
          this.path = []
          console.log(e.lnglat)
          let lnglat = e.lnglat
          this.lnglatpoints.push({
            latitude: lnglat.lat,
            longitude: lnglat.lng
          })
          console.log(this.lnglatpoints)
          this.lnglatpoints.map((val: any, index: number) => {
            console.log(index)
            if (index === 0) {
              this.map.center = [val.longitude, val.latitude]
            }
            let arr = [val.longitude, val.latitude]
            this.path.push(arr)
          })
          // this.setFitView()
        }
      }
    }
  }// 获取接送范围集合
  details() {
    const loading = this.$loading({
      lock: true,
      text: '加载中...'
    })
    api.main.boss_line_point__get({ params: {param: this.id}}).then((res: any) => {
        if (res.data.success) {
          const response = res.data.data
          this.formData = response
          let points = res.data.data.points
          if (points != null) {
            for (let i = 0; i < points.length; i++) {
              points[i].id = i
            }
            this.lnglatpoints = points
            this.lnglatpoints.map((val: any, index: number) => {
              if (index === 0) {
                this.map.center = [val.longitude, val.latitude]
              }
              let arr = [val.longitude, val.latitude]
              this.path.push(arr)
            })
          } else {
            this.map.center = [
              Number(this.formData.longitude),
              Number(this.formData.latitude)
            ]
            this.label.content = this.formData.location
          }
          setTimeout(this.setFitView, 0)
        } else {
          this.$message.error(res.data.message)
        }
        loading.close()
      })
  }

  // 移除经纬度
  deletes(data: any) {
    let e: any = this
    this.path = []
    for (let i = 0; i < e.lnglatpoints.length; i++) {
      if (
        data.latitude === e.lnglatpoints[i].latitude &&
        data.longitude === e.lnglatpoints[i].longitude
      ) {
        e.lnglatpoints.splice(i, 1)
      }
    }
    console.log(e.path)
    this.lnglatpoints.map((val: any, index: number) => {
      let arr = [val.longitude, val.latitude]
      this.path.push(arr)
      if (index === 0) {
        this.map.center = [val.longitude, val.latitude]
      }
      console.log(this.path)
    })
  }

  clear() {
    this.$confirm('确认删除绘制的接送区域?', '删除', {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      type: 'warning'
    })
      .then(() => {
        let self: any = this
        this.path = []
        this.lnglatpoints = []
        // this.map.center = [106.5507300000, 29.5647100000]
        this.lngLat = ''
        self.formData.points = []
      })
      .catch(() => {})
  }

  // 输入经纬度
  submitEnter() {
    // eslint-disable-next-line
    const illegalRegExp = /^(\D|\d*\.?\d*,*\s)|[^\d\s,\.]|^\d*\.?\d*$|(,\.|\.,)+|(\d*\.*\d*,){2,}|(\d*\.){2,}|(\d*\s){2,}|(\s\d*\.?\d*|\D)$/g
    const replaceWhiteSpaceRegExp = /(?<=(,|\.|\s))\s+|\s+(?=(,|\.))|^\s|\s+$/g

    this.lngLat = this.lngLat.replace(replaceWhiteSpaceRegExp, '')
    if (illegalRegExp.test(this.lngLat)) {
      return this.$message.error('经纬度格式错误!')
    }
    const lnglatArray = this.lngLat.split(' ')
    lnglatArray.forEach(lnglatString => {
      const lnglatObject = {
        longitude: lnglatString.split(',')[0],
        latitude: lnglatString.split(',')[1]
      }
      this.lnglatpoints.push(lnglatObject)
    })
    this.path = []
    this.lnglatpoints.map((val: any, index: number) => {
      let arr = [val.longitude, val.latitude]
      this.path.push(arr)
      this.lngLat = ''
      if (index === 0) {
        this.map.center = [val.longitude, val.latitude]
      }
    })
  }

  setFitView() {
    const vm: any = this
    let map = vm.$refs.map.$$getInstance()
    map.setFitView()
  }

  close() {
    this.$router.push({
      name: 'pointList'
    })
  }

  save() {
    let e: any = this
    let params: any = {}
    if (this.id !== '-1') {
      // 编辑
      e.formData.id = this.id
      params.id = this.id
    }
    e.formData.points = this.lnglatpoints
    if (e.formData.location === '' || e.formData.location === null) {
      this.$message.warning('名称不能为空!')
      return
    }
    if (this.lnglatpoints.length < 3 && e.formData.type === 2) {
      this.$message.warning('经纬度不能小于三组!')
      return
    }
    params.points = this.lnglatpoints
    params.location = this.formData.location
    params.longitude = this.formData.longitude
    params.latitude = this.formData.latitude
    if (this.id !== '-1') {
      api.main.boss_line_point_update_post({ data: params }).then((res: any) => {
          if (res.data.success) {
            this.$message.success('保存成功!')
            this.$router.push({
              name: 'pointList'
            })
          } else {
            this.$message.error(res.data.message)
          }
        })
    } else {
      api.main
        .boss_line_point_addAndBindLine_post({ data: params })
        .then((res: any) => {
          if (res.data.success) {
            this.$message.success('保存成功!')
            this.$router.push({
              name: 'pointList'
            })
          } else {
            this.$message.error(res.data.message)
          }
        })
    }
  }
}
</script>
<style lang="scss" scoped>
ul,
li {
  list-style: none;
  margin: 0;
  padding: 0;
}
.inline-form {
  display: flex;
  display: -webkit-flex;
  flex-direction: row;
  flex-wrap: wrap;
  .el-form-item {
    margin-bottom: 10px;
    margin-left: 15px;
    display: flex;
  }
  .el-button {
    margin-left: 15px;
    height: 32px;
  }
}
.action-bar {
  box-sizing: border-box;
  padding: 10px;
  padding-bottom: 0;

  border: {
    top: 1px solid #ddd;
    bottom: 1px solid #ddd;
  }
  .my-input {
    width: 150px;
  }
  .name-input {
    width: 260px;
  }
}
.el-select-dropdown__item {
  background-color: white;
  text-indent: 10px;
}
.claer {
  margin-top: 15px;
  float: right;
}

$map_height: calc(100vh - 55px - 50px - 75px - 15px);
.map-box {
  position: relative;

  height: $map_height;
  .map-tool {
    position: absolute;
    width: 220px;
    z-index: 170;
    top: 0;
    left: 0;
    max-height: 100%;

    box-sizing: border-box;
    padding: 10px;
    overflow-y: auto;

    background-color: #fff;
    box-shadow: 2px 4px 7px 1px #dedede;
  }
  .map {
    transition: all 0.6s;
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
  }
}
.swiper-box {
  position: relative;
  z-index: 161;

  display: flex;
  align-items: center;
  flex-direction: row;
  justify-content: center;

  width: 100%;

  transition: transform ease-in 0.6s;
  transform: translateX(0);
  white-space: nowrap;
  .swiper-item {
    width: 100%;
    height: $map_height;
  }
}
.hide-text-area {
  transform: translateX(-100%);
}
.gray-map {
  filter: grayscale(90%);
}
.longlat {
  margin-top: 15px;
  padding-bottom: 15px;

  ul {
    li {
      padding: 6px;
      background-color: #ddd;
      border-radius: 4px;
      margin-bottom: 15px;
      font-size: 14px;
      color: #666;
      position: relative;
    }
  }
}
.el-icon-close {
  display: inline-block;
  position: absolute;
  right: 10px;
  color: #000 !important;
  cursor: pointer;
}
.my-button {
  margin-bottom: 10px;
}
</style>

 三、第二种画化:使用AMap.MouseTool画多边形(效果是:多边形随鼠标左键点击,多边形直接跟着变化)

// 新增 编辑 查看 
<template>
  <div class="point">
    <el-header></el-header>
    <div class="action-bar">
      <el-form class="inline-form" :rules="rules" ref="formData" size="small" :model="formData">
        <el-form-item label  prop="location">
          <el-input
            :disabled="!ifFalg"
            class="name-input"
            clearable
            v-model="formData.location"
            placeholder="名称"
            maxlength="30"
          ></el-input>
        </el-form-item>
        <el-form-item label  prop="longitude">
          <el-input
            :disabled="!ifFalg"
            class="my-input"
            clearable
            v-model.number="formData.longitude"
            placeholder="经度 "
          ></el-input>
        </el-form-item>
        <el-form-item label  prop="latitude">
          <el-input
            :disabled="!ifFalg"
            class="my-input"
            clearable
            v-model.number="formData.latitude"
            placeholder="纬度"
          ></el-input>
        </el-form-item>
        <el-button class="my-button" v-if="ifFalg" type="primary" @click="save" size="small">保存</el-button>
        <el-button class="my-button" size="small" @click="close">关闭</el-button>
      </el-form>
    </div>
    <div class="map-box">
      <div class="map-tool">
        <div v-if="ifFalg">
          <el-checkbox >地图上描点</el-checkbox>
        </div>
        <div class="longlat">
          <ul><li v-for="(item, index) in lnglatpoints" :key="index">
              {{item.longitude}} , {{item.latitude}}
              <i
                v-if="ifFalg"
                class="el-icon-close"
                @click="deletes(item)"
              ></i>
            </li> 
          </ul>
          <br>
          <div>
            <span >输入范围经纬度:</span>
           <el-input
               type="textarea"
               autosize
               placeholder="请输入内容"
               v-model="lnglatpointsString">
            </el-input>
          </div>
          <el-button v-if="ifFalg" size="small" @click="clear1" type="primary" class="claer1">确定</el-button>
          <el-button v-if="ifFalg" size="small" @click="clear" type="primary" class="claer">清除</el-button>
        </div>
      </div>
      <div class="map" id="map">
        <el-amap
          ref="map"
          bubble
          :zoom="map.zoom"
          :center="map.center"
          :events="mapEvents"
          id="amap"
        >
          <el-amap-polygon
            :events="plugin.events"
            :path="path"
            fillColor="#2b83f9"
            fillOpacity="0.5"
            strokeWeight="0"
            strokeColor="#2b83f9"
            strokeOpacity="0.5"
          ></el-amap-polygon>
          <el-amap-marker v-if="formData.type === 1" :position="map.center" :label="label"></el-amap-marker>
        </el-amap>
    
      </div>
      <div class="my-tools">
        <el-row>
          <el-button type="primary" v-if="ifFalg" @click="drawPolygon()">鼠标绘制</el-button>
          <el-button type="primary" v-if="ifFalg" @click="polygonEditor.close()">结束编辑</el-button>
        </el-row>
    </div>
    </div>
  </div>
</template>
<script lang="ts">同上
 /**
   * 绘制多边形 
   */
  private drawPolygon () {
         let vm: any = this
         let map = vm.$refs.map.$$getInstance()
         map.plugin(['AMap.MouseTool'], function () {
           var mouseTool = new AMap.MouseTool(map)
          var drawPolygon = mouseTool.polygon()
           AMap.event.addListener(mouseTool, 'draw', function (e: any) {
             e.obj.Je.visible = false
             let path = e.obj.getPath()
                vm.drawPolygonsToMap(path)
              
               path.forEach((point:any) => {
                    vm.lnglatpoints.push({
                      latitude: point.lat,
                     longitude: point.lng
                    })
               });
               // vm.mapDates =path  
               // e.obj.hide()
               mouseTool.close()
           })
         })
       
  }
同上
}
</script>
<style lang="scss" scoped>
和上面一样
</style>

三、第三种画化:使用AMap.Polygon和AMap.PolyEditor画多边形(推荐,效果是:https://lbs.amap.com/api/javascript-api/example/overlayers/polygon-draw-and-edit

  注意哦:1、以为这种画多边形,先需要3个点来确定初始的多边形,所以添加了一个功能:搜索 (功能:点击搜索名称的经纬度;);

      2、然后我再 ‘范围绘制’ 的方法里根据“搜索”得来的经纬度,手动的弄了3个经纬度数组。

      3、然后就可以快乐的画图了。(这画图是真的方便,特别是画范围很复杂的)

// 新增 编辑 查看 
<template>
  <div class="point">
    <el-header></el-header>
    <div class="action-bar">
      <el-form class="inline-form" :rules="rules" ref="formData" size="small" :model="formData">
        <el-form-item label  prop="location">
          <el-input
            :disabled="!ifFalg"
            class="name-input"
            clearable
            v-model="formData.location"
            placeholder="名称"
            maxlength="30"
          ></el-input>
        </el-form-item>
     <el-button class="my-button"  type="info" @click="getLocation" size="small">搜索</el-button>
<el-form-item label prop="longitude"> <el-input :disabled="!ifFalg" class="my-input" clearable v-model.number="formData.longitude" placeholder="经度 " ></el-input> </el-form-item> <el-form-item label prop="latitude"> <el-input :disabled="!ifFalg" class="my-input" clearable v-model.number="formData.latitude" placeholder="纬度" ></el-input> </el-form-item> <el-button class="my-button" v-if="ifFalg" type="primary" @click="save" size="small">保存</el-button> <el-button class="my-button" size="small" @click="close">关闭</el-button> </el-form> </div> <div class="map-box"> <div class="map-tool"> <div v-if="ifFalg"> <el-checkbox >地图上描点</el-checkbox> </div> <div class="longlat"> <ul> <li v-for="(item, index) in lnglatpoints" :key="index"> {{item.longitude}} , {{item.latitude}} <i v-if="ifFalg" class="el-icon-close" @click="deletes(item)" ></i> </li> </ul> <br> <div> <span >输入范围经纬度:</span> <el-input type="textarea" autosize placeholder="请输入内容" v-model="lnglatpointsString"> </el-input> </div> <el-button v-if="ifFalg" size="small" @click="clear1" type="primary" class="claer1">确定</el-button> <el-button v-if="ifFalg" size="small" @click="clear" type="primary" class="claer">清除</el-button> </div> </div> 同上 <div class="my-tools"> <el-row> <el-button type="primary" v-if="ifFalg" @click="drawPolygon()">鼠标绘制</el-button> <el-button type="primary" v-if="ifFalg" @click="polygonEditor.close()">结束编辑</el-button> </el-row> </div> </div> </div> </template> <script lang="ts"> 同上
//画多边形
   private drawPolygon(){
    let vm: any = this
    if (vm.formData.location === '' || vm.formData.location === null) {
      this.$message.warning('请先输入名称,才能开始画范围!')
      return
    }
    let  map = new AMap.Map("map", {
        center:[106.55073, 29.56471],
        zoom: 15
    });
     // 多边形覆盖物节点坐标数组
    let polygonArr:any = [] 
    let lng = Number(this.formData.longitude) 
    let lat = Number(this.formData.latitude) 
    if(vm.path.length > 0){
        polygonArr = vm.path
    }else{
       polygonArr.push([lng, lat])
       polygonArr.push([lng, lat - 0.001])
       polygonArr.push([lng - 0.001, lat - 0.001])
    }   
    //使用 AMap.Polygon构建多边形
    let polygon = new AMap.Polygon({
        path:polygonArr,
        strokeColor: "#FF33FF", 
        strokeWeight: 6,
        strokeOpacity: 0.2,
        fillOpacity: 0.4,
        fillColor: '#1791fc',
        zIndex: 50,
    })
    //将多边形增加到地图上
    map.add(polygon)
    // 缩放地图到合适的视野级别
    map.setFitView([ polygon ])
    //构造折线编辑对象,并开启折线的编辑状态
    map.plugin(["AMap.PolyEditor"],function(){
     let polygonEditor = new AMap.PolyEditor(map,polygon); 
        vm.polygonEditor =polygonEditor
        polygonEditor.open(); 
      //关闭多边形编辑polygonEditor.close()触发该方法;
       polygonEditor.on('end', function(event:any) {
        // event.target 即为编辑后的多边形对象,event.target.getPath()得到编辑完成后的点数组
        let pointArr = event.target.getPath()
        vm.lnglatpoints = []
        pointArr.forEach((point:any)=>{
          vm.lnglatpoints.push({latitude: point.lat,longitude: point.lng})
        })
    
vm.path = []
        vm.lnglatpoints.map((val: any, index: number) => {
       let arr = [val.longitude, val.latitude]
       vm.path.push(arr)
       if (index === 0) {
        vm.map.center = [val.longitude, val.latitude]
       }
     })
    })
    });
  }
  /**
   * 地理编码(地址 -> 坐标)
   */
  private getLocation () {
   let loc = this.formData.location
    AMap.plugin('AMap.Geocoder', () => {
      let geocoder = new AMap.Geocoder()
      geocoder.getLocation(loc, (status: string, result: any) => {
        if (status === 'complete' && result.info === 'OK') {
          let { lat, lng } = result.geocodes[0].location
          if (lat && lng) {
            this.map.center = [lng, lat]
            this.formData.longitude=lng
            this.formData.latitude=lat
          }
        }
      })
    })
  }


  同上
}
</script>
<style lang="scss" scoped>
和上面一样
</style>

 

123

posted @ 2020-07-17 09:28  糊涂蜗牛  阅读(11056)  评论(4编辑  收藏  举报