Newer
Older
dcms_front / src / components / Map / arcgisMap.vue
yangqianqian on 28 Dec 2020 17 KB leaflet地图
<template>
  <div>
    <el-row :gutter="20">
      <el-col :span="4">
        <el-input v-model="keywords" size="small" type="text" placeholder="兴趣点关键字" clearable />
      </el-col>
      <el-col :span="4">
        <el-button type="primary" size="small" @click="queryOnMap">查询</el-button>
        <el-button type="info" size="small" @click="clearMap"> 清除地图 </el-button>
      </el-col>

      <el-col :span="8" style="text-align: center;">
        <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 label="2">兴趣点属性</el-radio-button>
        </el-radio-group>
      </el-col>

      <el-col v-if="queryEventSwitch === '0'" :span="8" style="text-align: right;">
        <el-select v-model="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="8" style="text-align: right;">
        <el-button type="primary" size="small" @click="checkEventPoint"> 事件提交 </el-button>
      </el-col>
    </el-row>

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

<script>
import { loadModules } from 'esri-loader'
import { mapConfig, serverConfig } from './ArcGISConfig'

const option = {
  url: mapConfig.apiUrl
}

const eventPointLayerId = 'eventPointLayer' // 事件定位点的图层id
const queryResultLayerId = 'queryResultLayer' // 兴趣点查询结果点集的图层id
const caseLayerId = 'addedGeometryLayerId' // 案卷点图层

export default {
  name: 'ArcGISMap',
  data() {
    return {
      map: '',
      view: '',
      layers: {
        dxbjPoint: '', // 部件点图层
        dxbjLine: '', // 部件线图层
        dxbjXqd: '', // 兴趣点图层
        dxbjMph: '', // 门牌好图层
        dx2wGrid: '' // 单元网格图层
      },
      esriObj: {
        Map: '',
        BaseMap: '',
        Graphic: '',
        PopupTemplate: '',
        Circle: '',
        Point: '',
        FeatureLayer: '',
        GraphicsLayer: '',
        TileLayer: '',
        SimpleMarkerSymbol: '',
        Query: '',
        QueryTask: '',
        IdentifyTask: '',
        IdentifyParameters: '',
        MapView: ''
      },
      keywords: '', // 查询关键字
      showEventPointPopup: true, // 是否显示事部件的popup
      queryEventSwitch: '1', // 1==查询事件;0==查询部件
      compListOpts: [], // 部件选择下拉框option
      // 主页面返回值
      longitude: '', // 定位点经度
      latitude: '', // 定位点纬度
      communityId: '', // 社区ID
      communityName: '', // 社区名称
      gridId: '', // 单元网格ID
      componentId: '', // 部件ID
      componentName: '' // 部件名称
    }
  },
  mounted() {
    this.importEsri()
  },
  methods: {
    // 初始化ArcGIS API对象
    importEsri: function() {
      loadModules([
        'esri/Map',
        'esri/Basemap',
        'esri/Graphic',
        'esri/PopupTemplate',
        'esri/geometry/Circle',
        'esri/geometry/Point',
        'esri/layers/FeatureLayer',
        'esri/layers/GraphicsLayer',
        'esri/layers/TileLayer',
        'esri/symbols/SimpleMarkerSymbol',
        'esri/tasks/support/Query',
        'esri/tasks/QueryTask',
        'esri/tasks/IdentifyTask',
        'esri/tasks/support/IdentifyParameters',
        'esri/views/MapView',
        'dojo/domReady!'
      ], option)
        .then(([
          Map,
          BaseMap,
          Graphic,
          PopupTemplate,
          Circle,
          Point,
          FeatureLayer,
          GraphicsLayer,
          TileLayer,
          SimpleMarkerSymbol,
          Query,
          QueryTask,
          IdentifyTask,
          IdentifyParameters,
          MapView
        ]) => {
          this.esriObj.Map = Map
          this.esriObj.BaseMap = BaseMap
          this.esriObj.Graphic = Graphic
          this.esriObj.PopupTemplate = PopupTemplate
          this.esriObj.Circle = Circle
          this.esriObj.Point = Point
          this.esriObj.FeatureLayer = FeatureLayer
          this.esriObj.GraphicsLayer = GraphicsLayer
          this.esriObj.TileLayer = TileLayer
          this.esriObj.SimpleMarkerSymbol = SimpleMarkerSymbol
          this.esriObj.Query = Query
          this.esriObj.QueryTask = QueryTask
          this.esriObj.IdentifyTask = IdentifyTask
          this.esriObj.IdentifyParameters = IdentifyParameters
          this.esriObj.MapView = MapView

          // 初始化地图
          this.initMap()
        }).catch(err => {
          console.log(err)
        })
    },
    // 初始化地图
    initMap: function() {
      const base = new this.esriObj.BaseMap({
        baseLayers: [
          new this.esriObj.TileLayer({ // 可配置属性,见TileLayer类
            id: '2w',
            url: serverConfig.mapUrlBase
          })
        ],
        title: 'dx2w',
        id: 'dx2w'
      })

      this.map = new this.esriObj.Map({
        basemap: base // 底图类型,详见BaseMap类
      })

      this.view = new this.esriObj.MapView({
        container: this.$refs.mapDiv, // 视图的容器
        map: this.map, // Map的实例放入视图中
        center: [116.597, 28.24], // 初始显示的地图中心点,经纬度
        zoom: 3 // 当前地图缩放等级
      })
      this.view.ui._removeComponents(['zoom'])

      const that = this
      this.view.on('click', function(event) {
        // 清除地图上已有的事件/部件查询点
        that.clearEOrCPoint()

        const lon = event.mapPoint.longitude
        const lat = event.mapPoint.latitude

        if (that.showEventPointPopup) {
          // 添加点
          const gLayer = new that.esriObj.GraphicsLayer()
          const marker = new that.esriObj.SimpleMarkerSymbol()
          marker.color = '#35A0E7'
          marker.style = 'square'
          marker.outline = {
            color: [128, 128, 128, 0.5],
            width: '2px'
          }
          const graphic = new that.esriObj.Graphic({
            geometry: event.mapPoint,
            symbol: marker
          })

          gLayer.id = eventPointLayerId
          gLayer.add(graphic)
          that.map.add(gLayer)

          // 查询事件或者部件
          if (that.queryEventSwitch === '1') {
            // 事件定位
            // 1查询底图得到所在网格与所在社区
            const query = that.layers.dx2wGrid.createQuery()
            query.geometry = that.view.toMap(event)
            query.distance = 10
            query.units = 'meters'
            query.returnGeometry = true
            query.outFields = ['BGID', 'COMMUID', 'COMMUNAME']
            console.log(that.layers.dx2wGrid)
            that.layers.dx2wGrid.queryFeatures(query)
              .then(function(response) {
                console.log(response)
                const result = response.features[0].attributes

                // 赋值
                that.longitude = lon
                that.latitude = lat
                that.gridId = result.BGID
                that.communityId = result.COMMUID
                that.communityName = result.COMMUNAME

                // 2弹出气泡
                that.view.popup.open({
                  title: '事件定位',
                  content: '坐标:[' + lon.toFixed(4) + ', ' + lat.toFixed(4) + ']' + '<p>' + '所在社区:' + result.COMMUNAME,
                  location: event.mapPoint
                })
              })
          } else if (that.queryEventSwitch === '0') {
            // 部件定位
            const queryDev = that.layers.dxbjPoint.createQuery()
            // 定义查询的圆形范围,半径5米
            const circle = new that.esriObj.Circle({
              center: event.mapPoint,
              radius: 5,
              radiusUnit: 'meters'
            })
            queryDev.geometry = circle
            queryDev.returnGeometry = true
            queryDev.outFields = ['BGID', 'OBJID', 'OBJNAME', 'OBJPOS']
            that.layers.dxbjPoint.queryFeatures(queryDev)
              .then(function(response) {
                if (response.features.length > 0) {
                  const results = response.features

                  that.compListOpts = []

                  let content = ''
                  results.forEach((item, index) => {
                    content += '<p>部件' + (index + 1) + ':' + item.attributes.OBJNAME + ',' + item.attributes.OBJPOS
                    const comp = {}
                    comp.name = '部件' + (index + 1) + ':' + item.attributes.OBJNAME
                    comp.value = item.attributes.OBJID
                    that.compListOpts.push(comp)
                  })

                  // 2弹出气泡
                  that.view.popup.open({
                    title: '部件定位',
                    content: '坐标:[' + lon.toFixed(4) + ', ' + lat.toFixed(4) + '],附近5米的部件有:' + content,
                    location: event.mapPoint
                  })

                  // 查询所在社区和单元网格
                  const queryPos = that.layers.dx2wGrid.createQuery()
                  queryPos.geometry = that.view.toMap(event)
                  queryPos.returnGeometry = true
                  queryPos.outFields = ['BGID', 'COMMUID', 'COMMUNAME']
                  that.layers.dx2wGrid.queryFeatures(queryPos)
                    .then(function(response) {
                      const result = response.features[0].attributes

                      // 赋值
                      that.longitude = lon
                      that.latitude = lat
                      that.gridId = result.BGID
                      that.communityId = result.COMMUID
                      that.communityName = result.COMMUNAME
                    })
                } else {
                  that.$message({
                    message: '没有查询到部件,请重新定位',
                    type: 'warning'
                  })
                }
              })
          }
        } else {
          that.view.hitTest(event).then(function(response) {
            if (response.results.length) {
              const graphic = response.results[0].graphic
              const name = graphic.attributes.KEYWORD
              const address = graphic.attributes.OBJPOS

              that.view.popup.open({
                title: name,
                content: address,
                location: graphic.geometry
              })
            }
          })
        }
      })

      this.addBjLayers()
      // this.addCasePointOnMap(116.5937, 28.249)
    },
    // 加载部件服务的各图层
    addBjLayers: function() {
      // 此处可以优化
      this.layers.dxbjPoint = new this.esriObj.FeatureLayer({ // 可配置属性,见TileLayer类
        url: serverConfig.mapUrlBj + '/0',
        id: 'dxbjPoint'
      })
      this.layers.dxbjLine = new this.esriObj.FeatureLayer({ // 可配置属性,见TileLayer类
        url: serverConfig.mapUrlBj + '/1',
        id: 'dxbjLine'
      })
      this.layers.dxbjXqd = new this.esriObj.FeatureLayer({ // 可配置属性,见TileLayer类
        url: serverConfig.mapUrlBj + '/2',
        id: 'dxbjXqd'
      })
      this.layers.dxbjMph = new this.esriObj.FeatureLayer({ // 可配置属性,见TileLayer类
        url: serverConfig.mapUrlBj + '/3',
        id: 'dxbjMph'
      })
      this.layers.dx2wGrid = new this.esriObj.FeatureLayer({
        url: serverConfig.mapUrlBase + '/6',
        id: 'gridLayer'
      })

      // 加载各图层
      this.map.add(this.layers.dxbjPoint)
      this.map.add(this.layers.dxbjLine)
      this.map.add(this.layers.dxbjXqd)
      this.map.add(this.layers.dxbjMph)
      this.map.add(this.layers.dx2wGrid)
    },
    // 在兴趣点图层查询关键字
    queryOnMap: function() {
      const points = [] // 查询结果点集

      this.clearQueryResults()
      this.clearEOrCPoint()
      this.showEventPointPopup = false
      this.queryEventSwitch = '2'

      // 查询条件
      const query = new this.esriObj.Query()
      query.returnGeometry = true
      query.outFields = ['*']
      query.where = 'NAME like ' + "'%" + this.keywords + "%'"
      const that = this

      this.layers.dxbjXqd.queryFeatures(query).then(function(results) {
        results.features.forEach(item => {
          const point = {}
          point.x = item.geometry.longitude
          point.y = item.geometry.latitude
          point.attr = item.attributes
          points.push(point)
        })

        // 提示查询结果
        if (points.length > 0) {
          that.$message({
            message: '成功查询到' + points.length + '条记录',
            type: 'success'
          })

          // 绘制点
          that.addSimpleMarkerOnMap(points)
        } else {
          that.$message({
            message: '没有查询到结果,请重新输入关键字',
            type: 'warning'
          })
        }
      })
    },
    // 清除图层上的查询结果
    clearQueryResults: function() {
      this.map.layers.forEach(layer => {
        if (layer.type === 'graphics' && layer.id === queryResultLayerId) {
          layer.graphics.removeAll()
          return false
        }
      })
    },
    // 清除图层上的查询结果
    clearMap: function() {
      // 清除地图上绘制的graphic图层
      this.map.layers.forEach(layer => {
        if (layer.type === 'graphics') {
          layer.graphics.removeAll()
          return false
        }
      })

      // 清除弹出框
      this.view.popup.close()

      // 清除data属性值
      this.keywords = ''
      this.showEventPointPopup = true // 是否显示事部件的popup
      this.queryEventSwitch = '1' // 1==查询事件;0==查询部件
      this.compListOpts = [] // 部件选择下拉框option
      this.longitude = '' // 定位点经度
      this.latitude = '' // 定位点纬度
      this.communityId = '' // 社区ID
      this.communityName = '' // 社区名称
      this.gridId = '' // 单元网格ID
      this.componentId = '' // 部件ID
      this.componentName = '' // 部件名称
    },
    // 清除图层上的事件定位点
    clearEOrCPoint: function() {
      this.map.layers.forEach(layer => {
        if (layer.type === 'graphics' && layer.id === eventPointLayerId) {
          layer.graphics.removeAll()
          return false
        }
      })
      // 清除弹出框
      this.view.popup.close()
    },
    // 切换
    switchEventOrComponent: function() {
      // 如果选中的是事件定位(1)或部件定位(0),点击地图时弹出事件或者部件的popup;否则(2以上)显示兴趣点结果的属性popup
      this.showEventPointPopup = this.queryEventSwitch < 2
    },
    // 将查询结果点集合绘制在地图上
    addSimpleMarkerOnMap: function(points) {
      const gLayer = new this.esriObj.GraphicsLayer()
      points.forEach(item => {
        const point = new this.esriObj.Point(item.x, item.y, item.attr)
        const marker = new this.esriObj.SimpleMarkerSymbol()
        marker.color = '#F9690E'
        marker.outline = {
          color: [128, 128, 128, 0.5],
          width: '2px'
        }
        const graphic = new this.esriObj.Graphic({
          geometry: point,
          symbol: marker,
          attributes: item.attr
        })
        gLayer.id = queryResultLayerId
        gLayer.add(graphic)
      })
      this.map.add(gLayer)
    },
    // 返回事件定位的结果
    checkEventPoint: function() {
      this.$emit(
        'closeMapQueryDialogByEvent',
        this.longitude,
        this.latitude,
        this.communityId,
        this.communityName,
        this.gridId)

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

      this.clearMap()
    },
    // 在地图上添加指定坐标的点
    addCasePointOnMap: function(lng, lat) {
      const gLayer = new this.esriObj.GraphicsLayer() // 添加自定义绘制点的图层
      const point = new this.esriObj.Point(lng, lat) // 创建geometry对象
      const marker = new this.esriObj.SimpleMarkerSymbol() // 创建marker标识
      // marker属性
      marker.color = '#F9690E'
      marker.outline = {
        color: [128, 128, 128, 0.5],
        width: '2px'
      }
      // 创建graphic对象
      const graphic = new this.esriObj.Graphic({
        geometry: point,
        symbol: marker
      })
      gLayer.id = caseLayerId // 标识案卷图层
      gLayer.add(graphic) // 图层上添加对象
      this.map.add(gLayer) // 地图上添加图层

      // 重新设置地图中心点并移动
      this.view.center = point
      this.view.goTo()
    }
  }
}
</script>

<style scoped>
   /*@import 'http://192.168.8.205/arcgis_js_api/library/4.12/esri/css/main.css';*/
  @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;
  }
</style>