Newer
Older
dcms_front / src / components / Map / leafletMap.vue
zhangyingjie on 8 May 2021 12 KB 案件地图改为leaflet调用
<template>
  <div style="margin-top: -10px">
    <el-row :gutter="20">
      <div v-show="showpoi">
        <el-col :span="3">
          <el-input v-model="keywords" size="small" type="text" placeholder="兴趣点关键字" clearable />
        </el-col>
        <el-col :span="5">
          <el-button type="primary" size="small" @click="queryOnMap">查询</el-button>
          <el-button type="info" size="small" @click="clearMap"> 清除地图 </el-button>
        </el-col>
      </div>

      <el-col :span="6" :offset="8" style="text-align: right;">
        <el-radio-group v-model="queryEventSwitch" size="small" @change="switchEventOrComponent">
          <el-radio-button label="1">事件定位</el-radio-button>
          <el-radio-button label="0">部件定位</el-radio-button>
          <el-radio-button v-show="showpoi" label="2">兴趣点属性</el-radio-button>
        </el-radio-group>
      </el-col>

      <el-col v-if="queryEventSwitch === '0'" :span="10" :offset="0" style="text-align: right;">
        <el-select v-model="form.componentId" placeholder="选择部件" clearable value="" size="small">
          <el-option
            v-for="item in compListOpts"
            :key="item.value"
            :label="item.name"
            :value="item.value"/>
        </el-select>
        <el-button type="primary" size="small" @click="checkComponentPoint"> 部件提交 </el-button>
      </el-col>

      <el-col v-if="queryEventSwitch === '1'" :span="10" :offset="0" style="text-align: right;">
        <el-button type="primary" size="small" @click="checkEventPoint"> 事件提交 </el-button>
      </el-col>
    </el-row>

    <div id="map" ref="mapDiv" class="baseMap"/>
  </div>
</template>

<script>
import L from 'leaflet'
import 'leaflet/dist/leaflet.css'
import { mapConfig, serverConfig } from './ArcGISConfig'
const esri = require('esri-leaflet')

export default {
  name: 'LeafletMap',
  data() {
    return {
      map: null,
      markers: [],
      layers: {
        bjPoint: '', // 部件点图层
        grid: '' // 单元网格图层
      },
      form: {
        longitude: '', // 定位点经度
        latitude: '', // 定位点纬度
        communityId: '', // 社区ID
        communityName: '', // 社区名称
        gridId: '', // 单元网格ID
        componentId: '', // 部件ID
        componentName: '' // 部件名称
      }, // 主页面返回值
      showpoi: false,
      keywords: '', // 查询关键字
      showEventPointPopup: true, // 是否显示事部件的popup
      queryEventSwitch: '1', // 1==查询事件;0==查询部件
      compListOpts: [] // 部件选择下拉框option
    }
  },
  mounted() {
    this.initMap()
  },
  methods: {
    initMap() {
      const map = L.map('map', {
        minZoom: 13,
        // maxZoom: 18,
        center: [27.755, 116.08],
        zoom: 16,
        zoomControl: false,
        attributionControl: false,
        crs: L.CRS.EPSG3857
      })
      map.doubleClickZoom.disable()
      this.map = map // data上需要挂载
      window.map = map

      esri.dynamicMapLayer({
        url: serverConfig.mapUrlBase
      }).addTo(map)

      this.addLayers()

      const that = this
      map.on('click', function(e) {

        console.log('e', e)
        console.log('e.latlng', e.latlng)
        console.log('queryEventSwitch', that.queryEventSwitch)
        that.clearPoints()

        // 加载定位点
        if (that.showEventPointPopup) {
          const icon = L.icon({
            iconUrl: require('../../assets/icons/icon-position.png'),
            iconSize: [35, 35]
          })
          const pos = L.marker(e.latlng, {
            icon: icon
          })
          that.markers.push(pos)
          that.map.addLayer(pos)

          // 查询事件或者部件
          if (that.queryEventSwitch === '1') {
            // 事件定位
            // 1查询底图得到所在网格与所在社区
            const query = that.layers.grid.query()
            query.nearby(e.latlng, 10)
            query.run(function(error, featureCollection, response) {
              if (error) {
                console.log(error)
                return
              }
              const result = featureCollection.features[0].properties
              // 赋值
              that.form.longitude = e.latlng.lng
              that.form.latitude = e.latlng.lat
              that.form.gridId = result.CommuId
              that.form.communityId = result.CommuId
              that.form.communityName = result.CommuName

              pos.bindPopup('坐标:[' + that.form.longitude.toFixed(4) + ', ' + that.form.latitude.toFixed(4) + ']' + '<p>' + '所在社区:' + result.CommuName).openPopup()
            })
          } else if (that.queryEventSwitch === '0') {
            var latlngs = []
            var p1 = that.getLonAndLat(e.latlng.lng, e.latlng.lat, 0, 2.5)
            latlngs.push([p1.lat, p1.lon])
            var p2 = that.getLonAndLat(e.latlng.lng, e.latlng.lat, 90, 2.5)
            latlngs.push([p2.lat, p2.lon])
            var p3 = that.getLonAndLat(e.latlng.lng, e.latlng.lat, 180, 2.5)
            latlngs.push([p3.lat, p3.lon])
            var p4 = that.getLonAndLat(e.latlng.lng, e.latlng.lat, 270, 2.5)
            latlngs.push([p4.lat, p4.lon])

            var polyline = L.polygon(latlngs)
            const bjQuery = that.layers.bjPoint.query()
            bjQuery.within(polyline)
            bjQuery.run(function(error, featureCollection, response) {
              if (error) {
                console.log(error)
                return
              }
              if (featureCollection.features.length > 0) {
                const result = featureCollection.features
                console.log(result)
                // 赋值
                that.compListOpts = []
                let content = ''
                result.forEach((item, index) => {
                  content += '<p>部件' + (index + 1) + ':' + item.properties.大类名称 + '-' + item.properties.小类名称 + '-' + item.properties.编码
                  const comp = {}
                  comp.name = '部件' + (index + 1) + ':' + item.properties.大类名称 + '-' + item.properties.小类名称 + '-' + item.properties.编码
                  comp.value = item.properties.编码
                  that.compListOpts.push(comp)
                })

                pos.bindPopup('坐标:[' + e.latlng.lng.toFixed(4) + ', ' + e.latlng.lat.toFixed(4) + '],附近5米的部件有:' + content).openPopup()

                const query = that.layers.grid.query()
                query.nearby(e.latlng, 10)
                query.run(function(error, featureCollection, response) {
                  if (error) {
                    console.log(error)
                    return
                  }
                  const result = featureCollection.features[0].properties
                  // 赋值
                  that.form.longitude = e.latlng.lng
                  that.form.latitude = e.latlng.lat
                  that.form.gridId = result.CommuId
                  that.form.communityId = result.CommuId
                  that.form.communityName = result.CommuName
                })
              } else {
                that.$message({
                  message: '没有查询到部件,请重新定位',
                  type: 'warning'
                })
              }
            }
            )
          }
        }
      })
    },
    addLayers() {
      this.layers.bjPoint = esri.featureLayer({
        url: serverConfig.mapUrlBj + '/0'
      })
      this.layers.grid = esri.featureLayer({
        url: serverConfig.mapUrlBase + '/16'
      })
      this.map.addLayer(this.layers.bjPoint)
      this.map.addLayer(this.layers.grid)
    },
    switchEventOrComponent: function() {
      // 如果选中的是事件定位(1)或部件定位(0),点击地图时弹出事件或者部件的popup;否则(2以上)显示兴趣点结果的属性popup
      this.showEventPointPopup = this.queryEventSwitch < 2
      this.clearPoints()
    },
    clearPoints() {
      const that = this
      this.markers.forEach(marker => {
        that.map.removeLayer(marker)
      })
    },
    // 返回事件定位的结果
    checkEventPoint: function() {
      this.$emit(
        'closeMapQueryDialogByEvent',
        this.form.longitude,
        this.form.latitude,
        this.form.communityId,
        this.form.communityName,
        this.form.gridId)

      this.clearMap()
    },
    // 返回部件定位的结果
    checkComponentPoint: function() {
      this.$emit(
        'closeMapQueryDialogByComp',
        this.form.longitude,
        this.form.latitude,
        this.form.communityId,
        this.form.communityName,
        this.form.gridId,
        this.form.componentId)

      this.clearMap()
    },
    clearMap() {
      this.clearPoints()
      // 清除data属性值
      this.keywords = ''
      this.showEventPointPopup = true // 是否显示事部件的popup
      this.queryEventSwitch = '1' // 1==查询事件;0==查询部件
      this.compListOpts = [] // 部件选择下拉框option
      this.form.longitude = '' // 定位点经度
      this.form.latitude = '' // 定位点纬度
      this.form.communityId = '' // 社区ID
      this.form.communityName = '' // 社区名称
      this.form.gridId = '' // 单元网格ID
      this.form.componentId = '' // 部件ID
      this.form.componentName = '' // 部件名称
    },
    numberToRadius(t) {
      return (t * Math.PI) / 180
    },
    numberToDegree(t) {
      return (180 * t) / Math.PI
    },
    /**
     * 根据一个经纬度及距离角度,算出另外一个经纬度
     * @param {*} lon 经度 113.3960698
     * @param {*} lat 纬度 22.941386
     * @param {*} brng 方位角 45 ---- 正北方:000°或360° 正东方:090° 正南方:180° 正西方:270°
     * @param {*} dist 90000距离(米)
     */
    getLonAndLat(lon, lat, brng, dist) {
      // 大地坐标系资料WGS-84 长半径a=6378137 短半径b=6356752.3142 扁率f=1/298.2572236
      var a = 6378137
      var b = 6356752.3142
      var f = 1 / 298.257223563
      var lon1 = lon * 1
      var lat1 = lat * 1
      var s = dist
      var alpha1 = this.numberToRadius(brng)
      var sinAlpha1 = Math.sin(alpha1)
      var cosAlpha1 = Math.cos(alpha1)
      var tanU1 = (1 - f) * Math.tan(this.numberToRadius(lat1))
      var cosU1 = 1 / Math.sqrt((1 + tanU1 * tanU1)), sinU1 = tanU1 * cosU1
      var sigma1 = Math.atan2(tanU1, cosAlpha1)
      var sinAlpha = cosU1 * sinAlpha1
      var cosSqAlpha = 1 - sinAlpha * sinAlpha
      var uSq = cosSqAlpha * (a * a - b * b) / (b * b)
      var A = 1 + uSq / 16384 * (4096 + uSq * (-768 + uSq * (320 - 175 * uSq)))
      var B = uSq / 1024 * (256 + uSq * (-128 + uSq * (74 - 47 * uSq)))
      var sigma = s / (b * A), sigmaP = 2 * Math.PI
      while (Math.abs(sigma - sigmaP) > 1e-12) {
        var cos2SigmaM = Math.cos(2 * sigma1 + sigma)
        var sinSigma = Math.sin(sigma)
        var cosSigma = Math.cos(sigma)
        var deltaSigma = B * sinSigma * (cos2SigmaM + B / 4 * (cosSigma * (-1 + 2 * cos2SigmaM * cos2SigmaM) -
          B / 6 * cos2SigmaM * (-3 + 4 * sinSigma * sinSigma) * (-3 + 4 * cos2SigmaM * cos2SigmaM)))
        sigmaP = sigma
        sigma = s / (b * A) + deltaSigma
      }
      var tmp = sinU1 * sinSigma - cosU1 * cosSigma * cosAlpha1
      var lat2 = Math.atan2(sinU1 * cosSigma + cosU1 * sinSigma * cosAlpha1, (1 - f) * Math.sqrt(sinAlpha * sinAlpha + tmp * tmp))
      var lambda = Math.atan2(sinSigma * sinAlpha1, cosU1 * cosSigma - sinU1 * sinSigma * cosAlpha1)
      var C = f / 16 * cosSqAlpha * (4 + f * (4 - 3 * cosSqAlpha))
      var L = lambda - (1 - C) * f * sinAlpha * (sigma + C * sinSigma * (cos2SigmaM + C * cosSigma * (-1 + 2 * cos2SigmaM * cos2SigmaM)))
      var revAz = Math.atan2(sinAlpha, -tmp) // final bearing
      var lonLatObj = { lon: lon1 + this.numberToDegree(L), lat: this.numberToDegree(lat2) }
      return lonLatObj
    }
  }
}
</script>

<style scoped>
  @import 'https://js.arcgis.com/4.13/esri/css/main.css';
  .baseMap {
    height:60vh;
    width: 100%;
    margin-top: 25px;
    border: 1px solid #DCDCDC;
    border-radius: 4px;
  }
  .leaflet-container {
    background: #fff0;
  }
</style>