• 最全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)|[^ds,.]|^d*.?d*$|(,.|.,)+|(d*.*d*,){2,}|(d*.){2,}|(d*s){2,}|(sd*.?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

  • 相关阅读:
    IM服务器架构实现
    TCP打洞技术
    Java的守护线程与非守护线程
    SQL中时间为空的处理小结
    tfs
    Silverlight技术总结
    PMS
    Silverlight的TabControl的selectionChanged事件中读取不到TextBox值的bug。
    hahahahahah
    APM文章
  • 原文地址:https://www.cnblogs.com/dupenghui/p/13327984.html
Copyright © 2020-2023  润新知