vue高德地图围栏选择及自由区域框选

47 阅读4分钟

好几年前写的了,之前公司有这个需求,左键点击自由区域,右键取消。地图是用的vue-amap集成的高德地图,支持高德地图本身的api,选择之后判断所选区域内是否存在商户.

  <div class="amap-page-container flex_column">
    <div class="nav flex_b_center shadow_border_normal">
      <div class="navLeft">
        <span class="area">发货方:</span>
        <el-select v-model="value1" clearable placeholder="请选择">
          <el-option v-for="item in option" :key="item.value" :label="item.label" :value="item.value" />
        </el-select>
        <el-checkbox v-model="checked" class="alreadyEquipped">已配驱仓</el-checkbox>
        <el-button type="primary" plain class="alreadyEquipped screen">筛选</el-button>
        <el-button type="text" class="alreadyEquipped">更多筛选</el-button>
      </div>
      <div>
        <el-button type="success" class="draw enclosure" plain @click="addFence">添加围栏</el-button>
        <el-button type="success" class="draw" plain @click="removeFence">清除围栏</el-button>
      </div>
    </div>
    <div class="section main flex_1_auto shadow_border_normal flex_column">
      <div class="toolbar section_title">当前坐标: {{ lng }}, {{ lat }}</div>
      <el-amap vid="amapDemo" :center="center" :zoom="zoom" class="amap-demo flex_1_auto" :events="events" pitch-enable="false" :amap-manager="amapManager">
        <el-amap-marker v-for="marker in markers" :key="marker.title" :events="marker.events" :position="marker.position" :icon="marker.icon" />
        <el-amap-polygon v-for="(item, index) in polygons" :key="index" :path="item.path" :fill-color="item.bgc" stroke-color="#ccc" stroke-opacity="0.5" stroke-style="solid" />
        <el-amap-info-window v-if="window" :position="window.position" :visible="window.visible" :content="window.content" :offset="window.offset" :close-when-click-map="true" :is-custom="true">
          <div id="info-window">
            <div class="info-box">
              <span>{{ window.title }}</span>
              <p>电话:{{ window.phone }}</p>
              <p>地址:{{ window.address }}</p>
            </div>
          </div>
        </el-amap-info-window>
      </el-amap>
    </div>
    <el-dialog title="运输订单明细" :close-on-click-modal="false" :close-on-press-escape="false" :visible.sync="dialogVisible" width="55%" :before-close="handleClose">
      <div class="table_box">
        <el-table
          :data="tableData"
          height="192"
          size="mini"
          stripe
          :row-style="{height: '20px'}"
          :cell-style="{padding: '0'}"
          border
          style="width: 100%"
          :header-cell-style="{ whiteSpace: 'nowrap', color: '#333', background: '#f5f5f5' }"
        >
          <el-table-column type="selection" width="55" />
          <el-table-column prop="orderNumber" label="订单号" />
          <el-table-column prop="state" label="出入库状态" />
          <el-table-column prop="inboundStatus" label="入站状态" />
          <el-table-column prop="shipper" label="托运人" />
          <el-table-column prop="store" label="门店" />
          <el-table-column prop="area" label="区县" />
          <el-table-column prop="street" label="街道" />
          <el-table-column prop="address" label="详细地址" width="180" />
          <el-table-column prop="package" label="包裹数" />
        </el-table>
      </div>
      <span slot="footer" class="dialog-footer">
        <el-button type="primary" @click="dialogVisible = false">保存调度单</el-button>
        <el-button @click="dialogVisible = false">关闭</el-button>
      </span>
    </el-dialog>
  </div>
import shop from '@/assets/img/shop.png'
import VueAMap from 'vue-amap'
const amapManager = new VueAMap.AMapManager()
export default {
  name: 'AmapPage',
  data: function() {
    const self = this
    return {
      data: [
        {
          position: '104.06588,30.711449',
          title: '金牛区超市',
          address: '四川省成都市金牛区',
          phone: '13333333333',
          url: shop
        },
        {
          position: '104.020531,30.647579',
          title: '武侯区超市',
          address: '四川省成都市武侯区',
          phone: '13333333334',
          url: shop
        },
        {
          position: '104.063156,30.76506',
          title: '金牛区超市2',
          address: '四川省成都市金牛区',
          phone: '13333333335',
          url: shop
        },
        {
          position: '103.882744,30.682142',
          title: '温江区超市',
          address: '四川省成都市温江区',
          phone: '13333333336',
          url: shop
        },
        {
          position: '103.921722,30.750826',
          title: '郫都区超市',
          address: '四川省成都市郫都区',
          phone: '13333333337',
          url: shop
        },
        {
          position: '103.596519,30.877319',
          title: '都江堰市超市',
          address: '四川省成都市都江堰市',
          phone: '13333333338',
          url: shop
        },
        {
          position: '104.271965,30.997131',
          title: '广汉市超市',
          address: '四川省成都市广汉市',
          phone: '13333333339',
          url: shop
        },
        {
          position: '103.669716,30.625669',
          title: '崇州市超市',
          address: '四川省成都市崇州市',
          phone: '13333333330',
          url: shop
        },
        {
          position: '104.096039,30.552134',
          title: '天府新区超市',
          address: '四川省成都市天府新区',
          phone: '13133333333',
          url: shop
        },
        {
          position: '104.190353,30.571352',
          title: '龙泉驿区超市',
          address: '四川省成都市龙泉驿区',
          phone: '13233333336',
          url: shop
        },
        {
          position: '104.272118,30.882921',
          title: '青白江区超市',
          address: '四川省成都市青白江区',
          phone: '13433333336',
          url: shop
        },
        {
          position: '103.92377,30.57447',
          title: '双流区超市',
          address: '四川省成都市双流区',
          phone: '13533333336',
          url: shop
        }
      ],
      zoom: 10, // 初始化地图显示层级
      center: [104.10194, 30.65984], // 地图中心点坐标
      markers: [],
      windows: [],
      window: '',
      checked: false,
      dialogVisible: false,
      amapManager,
      fenceForm: {
        coordinate: []
      },
      rectangle: null,
      mouseTool: null,
      overlays: [],
      // 发货方表单
      option: [
        {
          value: '选项1',
          label: '发货方1'
        },
        {
          value: '选项2',
          label: '发货方2'
        }
      ],
      // 订单追踪详情表单
      tableData: [
        {
          orderNumber: 'LP0D466724666943',
          state: '未出库',
          inboundStatus: '未收货',
          shipper: '',
          store: '赵小姐的店',
          area: '九龙坡区',
          street: '石桥铺街道',
          address: '重庆市沙坪坝区联芳街道香榭街80号-赵小姐的店',
          package: '3'
        },
        {
          orderNumber: 'LP0D466366979762',
          state: '未出库',
          inboundStatus: '未收货',
          shipper: '',
          store: '赵小姐的店',
          area: '九龙坡区',
          street: '石桥铺街道',
          address: '重庆市沙坪坝区联芳街道香榭街80号-赵小姐的店',
          package: '7'
        }
      ],
      // 区域
      polygons: [
        {
          path: [],
          bgc: 'rgba(80,237,23,0.5)'
        }
      ],
      retangles: [
        {
          center: [104.10194, 30.65984],
          bounds: [
            [104.10194, 30.65984],
            [104.30194, 30.85984]
          ],
          fillOpacity: 0.5,
          strokeColor: '#80d8ff',
          fillColor: '#ffffff',
          events: {
            click: e => {
              console.log(e.lnglat)
            }
          }
        }
      ],
      value1: '请选择发货方',
      // 多边形绘制(点击型) 左键标点 右键取消
      events: {
        click(e) {
          const { lng, lat } = e.lnglat
          self.lng = lng
          self.lat = lat
          const arr = []
          arr.push(lng)
          arr.push(lat)
          // console.log(lat)
          self.polygons.forEach(element => {
            element.path.push(arr)
          })
          self.markers.forEach(e => {
            var point = e.position
            self.polygons.forEach(element => {
              var isPointInRing = AMap.GeometryUtil.isPointInRing(point, element.path)
              if (isPointInRing == true) {
                self.dialogVisible = true
              }
            })
          })
        },
        rightclick() {
          self.polygons.forEach(element => {
            element.path = []
          })
        }
      },
      lng: 0,
      lat: 0
    }
  },
  mounted() {
    this.point()
  },
  methods: {
    point() {
      const markers = []
      const windows = []
      const that = this
      this.data.forEach((item, index) => {
        markers.push({
          position: item.position.split(','),
          icon: item.url,
          events: {
            click() {
              // 方法:鼠标移动到点标记上,显示相应窗体
              that.windows.forEach(window => {
                window.visible = false // 关闭窗体
              })
              that.window = that.windows[index]
              that.$nextTick(() => {
                that.window.visible = true
              })
            }
          }
        })
        windows.push({
          position: item.position.split(','),
          isCustom: true,
          offset: [115, 55], // 窗体偏移
          showShadow: false,
          visible: false, // 初始是否显示
          address: item.address,
          title: item.title,
          phone: item.phone
        })
      })
      //  加点
      this.markers = markers
      // 加弹窗
      this.windows = windows
    },
    handleClose() {},
    // 绘制矩形
    addFence() {
      const _this = this
      const map = amapManager.getMap()
      if (this.fenceForm.coordinate.length > 0) {
        alert('围栏已存在!')
        return
      }
      if (this.rectangle) {
        map.remove(this.rectangle)
      }
      map.plugin(['AMap.MouseTool'], function() {
        const mouseTool = new AMap.MouseTool(map)
        _this.mouseTool = mouseTool
        mouseTool.rectangle()
        AMap.event.addListener(mouseTool, 'draw', function(e) {
          _this.fenceForm.coordinate = []
          const path = e.obj.getPath()
          _this.markers.forEach(e => {
            var point = e.position
            var isPointInRing = AMap.GeometryUtil.isPointInRing(point, path)
            if (isPointInRing == true) {
              _this.dialogVisible = true
            }
          })
          path.forEach(e => {
            _this.fenceForm.coordinate.push([e.getLng(), e.getLat()])
          })
          mouseTool.close(false)
        })
      })
    },
    removeFence() {
      this.fenceForm.coordinate = []
      if (this.mouseTool) {
        this.mouseTool.close(true)
      }
      if (this.rectangle) {
        amapManager.getMap().remove(this.rectangle)
      }
    }
  }
}
.toolbar {
  padding: 10px;
  padding-top: 0;
  color: #4ea9ea;
}
.amap-demo {
  height: 100%;
  border-radius: 5px;
}

.amap-page-container {
  position: relative;
}

#info-window {
  width: 211px;
  height: 80px;
  margin-left: 30px;
  background: rgba(255, 255, 255, 0.9);
  border-radius: 4px;
  overflow: hidden;
  span {
    font-weight: bold;
    display: block;
    margin-top: 15px;
    margin-bottom: 5px;
  }
  .info-box {
    margin-left: 10px;
  }
}

.detail {
  width: 100%;
  height: 24px;
  color: #fff;
  background-color: #1a73e8;
  position: absolute;
  bottom: 0;
  font-size: 12px;
  line-height: 24px;
  text-align: center;
  cursor: pointer;
}
::v-deep .amap-icon img {
  width: 30px;
  height: 30px;
}
.nav {
  display: flex;
  background-color: #fff;
  padding: 10px;
  margin: 10px 10px 0;
  align-items: center;
  .navLeft {
    display: flex;
    align-items: center;
    .alreadyEquipped {
      margin: 0px 10px;
    }
  }
}
.main {
  margin-bottom: 10px;
  ::v-deep th{
    height: 20px;
    padding: 1px;
  }
}
::v-deep .el-dialog {
  background-color: #fff;
}