<template> <div> <div id="map" class="leaflet_container" style="background-color: white"> <div class="right-card" style="right: 150px;width: 200px"> <el-button style="height: 40px;width: 40px;padding: 0px" @click="drawSquare"> <img src="@/assets/global_images/square.png" style="height: 18px;width: 18px;"> </el-button> <el-button style="height: 40px;width: 40px;padding: 0px" @click="drawPolygon"> <img src="@/assets/global_images/polygon.png" style="height: 18px;width: 18px;"> </el-button> <el-button style="height: 40px;width: 40px;padding: 0px" @click="drawDelete"> <img src="@/assets/global_images/delete.png" style="height: 18px;width: 18px;"> </el-button> </div> <div class="right-card"> <el-row> <el-button icon="el-icon-copy-document" style="width: 100px;" @click="btnList=!btnList"> 图层<i class="el-icon-arrow-down el-icon--right"/></el-button> </el-row> <el-checkbox-group v-show="btnList" v-model="selectParts" style=" width: 130px;margin-top: 10px;position: absolute;right: 10px"> <el-checkbox key="底图" :disabled="checkboxloading" label="底图" border style="margin-left: 10px;width: 130px;background-color: white" @change="mapChange"/> <el-checkbox v-for="parts in partsOptions" :disabled="checkboxloading" :label="parts" :key="parts" border style="width: 130px;background-color: white" @change="partsChange">{{ parts }}</el-checkbox> </el-checkbox-group> </div> <div style="margin-top: 20px;position: absolute;left:50px;z-index: 100000"> <el-input v-model="keyword" placeholder="请输入查询条件" class="input-with-select" style="width: 300px;"> <el-button slot="append" :disabled="!cansearch" icon="el-icon-search" style="background-color: #409eff;color: white" @click="search"/> </el-input> <div v-show="isShow" class="search-total"> 共找到 {{ searchlist.length }} 条个查询结果 </div> <div v-show="isShow && searchlist.length!==0" class="table"> <el-table :data="showlist" :show-header="false" style="border-color: white"> <el-table-column key="编码" label="编码" width="298" align="left" show-overflow-tooltip> <template slot-scope="scope"> <el-row class="table-item"> <el-col :span="2"> <div class="item-icon"> {{ scope.$index + 1 }}</div> </el-col> <el-col :offset="2" :span="8" style="font-size: 12px;"> <el-row style="height: 18px">名称:{{ scope.row.properties.小类名称 }}</el-row> <el-row style="height: 18px">编码:{{ scope.row.properties.编码 }}</el-row> <el-row style="height: 18px;margin-bottom: 3px">地址:{{ scope.row.properties.OBJECTID }}</el-row> </el-col> </el-row> </template> </el-table-column> </el-table> <el-pagination :current-page="offset" :page-size="5" :total="searchlist.length" small style="background-color: white" align="center" layout="prev, pager, next" @current-change="handleCurrentChange"/> </div> </div> </div> </div> </template> <script> import L from 'leaflet' import 'leaflet/dist/leaflet.css' import { getServerList } from '@/api/server' var esri = require('esri-leaflet') const rainHole = [14] const sewageHole = [37] const video = [35] const lamp = [1, 3, 4, 22, 25, 34] const toilet = [12, 13, 41] const garbage = [24] const othersParts = [2, 5, 6, 7, 8, 9, 10, 11, 15, 16, 17, 18, 19, 20, 21, 23, 26, 27, 28, 29, 30, 31, 32, 33, 35, 36, 38, 39, 40, 42, 43, 44, 45] export default { name: 'MapSearch', data() { return { drawLayer: null, keyword: '', offset: 1, btnList: false, listLoading: false, // 加载动画 showlist: [], // 列表展示项 checkboxloading: false, list: [], // url列表 searchlist: [], cansearch: true, layerlist: [], map: null, bounds: null, showtable: true, isShow: false, partsOptions: ['网格', '商户', '视频监控点', '路灯杆和灯箱', '雨水井盖', '污水井盖', '公共厕所', '垃圾箱', '其他部件'], selectParts: ['底图', '网格', '商户', '视频监控点', '路灯杆和灯箱', '雨水井盖', '污水井盖', '公共厕所', '垃圾箱', '其他部件'], listQuery: { offset: 1, limit: 15 }, // 筛选条件 maps: [], parts: [], baseUrl: '', partsUrl: '', mapUrl: '', multipleSelection: [], // 多选选中项 baselayer: [], markerlist: [] } }, destroyed() { window.removeEventListener('click', this.handleKeyup, true) this.socket.close() }, mounted() { var southWest = L.latLng(27.74, 116.06) var northEast = L.latLng(27.77, 116.1) this.bounds = L.latLngBounds(southWest, northEast) window.addEventListener('click', this.handleKeyup, true) this.init() }, methods: { handleKeyup(val) { if (this.btnList && val.target.id === 'map') { this.btnList = false } }, addPointsToMap(results) { if (!results.hasOwnProperty('features') || results.features.length === 0) { return // no features, something went wrong } var features = results.features console.log(features) var feature var items = [] for (var i = 0; i < features.length; i++) { var symbol11 = new esri.symbol.SimpleFillSymbol(esri.symbol.SimpleFillSymbol.STYLE_SOLID, new esri.symbol.SimpleLineSymbol(esri.symbol.SimpleLineSymbol.STYLE_SOLID, new dojo.Color([0, 0, 255, 0.35]), 1), new dojo.Color([125, 125, 125, 0.35])) feature = features[i] feature.setSymbol(symbol11) this.map.graphics.add(feature) items.push(feature.attributes) } this.searchlist = items }, search() { this.cansearch = false var that = this this.searchlist = [] for (let i = 0; i < this.layerlist.length; i++) { var str = ['编码', '小类名称', '大类名称'] var query = esri.query({ url: this.baseUrl + this.partsUrl + '/' + this.layerlist[i].toString() }) if (this.keyword === '') { query.where('1=1') query.within(this.bounds) query.run(function(error, featureCollection, response) { if (error) { console.log(error) return } for (let j = featureCollection.features.length - 1; j >= 0; j--) { that.searchlist.push(featureCollection.features[j]) } if (i === that.layerlist.length - 1) { that.offset = 1 that.showlist = that.searchlist.slice(0, 5) that.isShow = true that.drawIcon() } console.log(featureCollection.features) }) } else { for (let j = 0; j < str.length; j++) { query.where(str[j] + " like '%" + this.keyword + "%'") query.within(this.bounds) query.run(function(error, featureCollection, response) { if (error) { console.log(error) return } for (let k = featureCollection.features.length - 1; k >= 0; k--) { that.searchlist.push(featureCollection.features[k]) } console.log(featureCollection.features) if (i === that.layerlist.length - 1) { that.offset = 1 that.showlist = that.searchlist.slice(0, 5) that.isShow = true that.drawIcon() } }) } } } }, drawIcon() { var that = this for (var i = 0; i < that.markerlist.length; i++) { that.map.removeLayer(that.markerlist[i]) } that.markerlist = [] for (let num = 0; num < that.showlist.length; num++) { var Icon switch (num) { case 0: Icon = L.icon({ iconUrl: require('../../assets/global_images/point1.png'), iconSize: [25, 25] }) break case 1: Icon = L.icon({ iconUrl: require('../../assets/global_images/point2.png'), iconSize: [25, 25] }) break case 2: Icon = L.icon({ iconUrl: require('../../assets/global_images/point3.png'), iconSize: [25, 25] }) break case 3: Icon = L.icon({ iconUrl: require('../../assets/global_images/point4.png'), iconSize: [25, 25] }) break case 4: Icon = L.icon({ iconUrl: require('../../assets/global_images/point5.png'), iconSize: [25, 25] }) break default: break } var item = L.marker([that.showlist[num].geometry.coordinates[1], that.showlist[num].geometry.coordinates[0]], { icon: Icon, id: that.showlist[num].properties }).addTo(that.map) that.markerlist.push(item) item.on('click', function(e) { console.log(e) if (e.target.dragging._marker._popup) { e.target.dragging._marker.unbindPopup() } var str = '<div style="font-size: 14px;width:200px;">' + '<div style="font-size: 14px;margin-bottom: 8px;">' + '<div>' + e.target.options.id.小类名称 + '</div></div>' + '<div style="padding-bottom: 4px"><col style="padding-right: 5px">大类:</col>' + e.target.options.id.大类名称 + '</div>' + '<div style="padding-bottom: 4px"><col style="padding-right: 5px">小类:</col>' + e.target.options.id.小类名称 + '</div>' + '<div style="padding-bottom: 4px"><col style="padding-right: 5px">部件编码:</col>' + e.target.options.id.编码 + '</div>' + '<div style="padding-bottom: 4px"><col style="padding-right: 5px">权属单位:</col>' + e.target.options.id.权属单位 + '</div>' + '<div style="padding-bottom: 4px"><col style="padding-right: 5px">详细地址:</col>' + e.target.options.id.详细地址 + '</div>' + '<div>' var popup = L.popup().setContent(str) e.target.dragging._marker.bindPopup(popup).openPopup() e.target.dragging._marker.openPopup() }) } this.cansearch = true }, drawDelete() { if (this.drawLayer) { this.drawLayer.layer.remove() } var southWest = L.latLng(27.74, 116.06) var northEast = L.latLng(27.77, 116.1) this.bounds = L.latLngBounds(southWest, northEast) this.search() }, drawSquare() { if (this.drawLayer) { this.drawLayer.layer.remove() } this.$nextTick(() => { this.map.pm.enableDraw('Rectangle', { snappable: false }) }) }, drawPolygon() { if (this.drawLayer) { this.drawLayer.layer.remove() } this.$nextTick(() => { this.map.pm.enableDraw('Polygon', { snappable: false }) }) }, mapChange(val) { if (!val) { // 隐藏底图 for (let i = 0; i < this.maps.length; i++) { this.map.removeLayer(this.maps[i]) } } else { for (let i = 0; i < this.maps.length; i++) { this.map.addLayer(this.maps[i]) } } }, partsChange(val, item) { this.checkboxloading = true var selectItem switch (item.target.defaultValue) { case '视频监控点': selectItem = video break case '路灯杆和灯箱': selectItem = lamp break case '公共厕所': selectItem = toilet break case '垃圾箱': selectItem = garbage break case '雨水井盖': selectItem = rainHole break case '污水井盖': selectItem = sewageHole break case '其他部件': selectItem = othersParts break default: selectItem = [] break } if (!val) { // 隐藏底图 for (let i = 0; i < selectItem.length; i++) { this.map.removeLayer(this.parts[selectItem[i] - 1]) for (let j = 0; j < this.layerlist.length; j++) { if (this.layerlist[j] === selectItem[i]) { this.layerlist.splice(j, 1) } } } } else if (val) { for (let i = 0; i < selectItem.length; i++) { this.map.addLayer(this.parts[selectItem[i] - 1]) var res = -1 for (let j = 0; j < this.layerlist.length; j++) { if (this.layerlist[j] === selectItem[i]) { res = j } } if (res === -1) { this.layerlist.push(selectItem[i]) } } } this.checkboxloading = false }, tableclick() { this.showtable = !this.showtable }, setZoom(points) { if (points.length > 0) { var maxLng = points[0][1] var minLng = points[0][1] var maxLat = points[0][0] var minLat = points[0][0] var res for (var i = points.length - 1; i >= 0; i--) { res = points[i] if (res[1] > maxLng) maxLng = res[1] if (res[1] < minLng) minLng = res[1] if (res[0] > maxLat) maxLat = res[0] if (res[0] < minLat) minLat = res[0] } var cenLng = (parseFloat(maxLng) + parseFloat(minLng)) / 2 var cenLat = (parseFloat(maxLat) + parseFloat(minLat)) / 2 var zoom = this.getZoom(maxLng, minLng, maxLat, minLat) this.map.setView({ lat: cenLat, lng: cenLng }, zoom) } else { // 没有坐标,显示全中国 this.map.setView({ lat: 103.388611, lng: 35.563611 }, 5) } }, getZoom(maxLng, minLng, maxLat, minLat) { var zoom = ['50', '100', '200', '500', '1000', '2000', '5000', '10000', '20000', '25000', '50000', '100000', '200000', '500000', '1000000', '2000000', '5000000']// 级别18到3。 var latlng = L.latLng(maxLat, maxLng) var distance = latlng.distanceTo(L.latLng(minLat, minLng)) // var distance = pointA.distanceTo(pointB)// 获取两点距离,保留小数点后两位 for (var i = 0, zoomLen = zoom.length; i < zoomLen; i++) { if (zoom[i] - distance > 0) { return 18 - i + 2 // 之所以会多2,是因为地图范围常常是比例尺距离的10倍以上。所以级别会增加3。 } } return 5 }, async init() { const map = L.map('map', { minZoom: 2, // maxZoom: 18, center: [27.755, 116.08], zoom: 18, zoomControl: false, attributionControl: false, crs: L.CRS.EPSG3857 }) map.doubleClickZoom.disable() this.map = map // data上需要挂载 window.map = map var that = this this.map.on('pm:create', e => { if (that.drawLayer) { that.drawLayer.layer.remove() } that.drawLayer = e }) const res = await getServerList(this.listQuery) this.list = res.data.rows for (var i = 0; i < this.list.length; i++) { if (this.list[i].name === 'GIS地图') { this.baseUrl = this.list[i].url } else if (this.list[i].name === '部件分层URL') { this.partsUrl = this.list[i].url } else if (this.list[i].name === '二维地图URL') { this.mapUrl = this.list[i].url } } // 底图 this.maps.push(esri.dynamicMapLayer({ url: this.baseUrl + this.mapUrl, minZoom: 4, // 最小缩放等级 maxZoom: 21// 最大缩放等级 }).addTo(map)) // 部件 for (let i = 1; i <= 45; i++) { this.layerlist.push(i) let item = { url: this.baseUrl + this.partsUrl + '/' + i.toString(), minZoom: 10 } if (i === 15) { item = { url: this.baseUrl + this.partsUrl + '/' + i.toString(), minZoom: 10, style: function(feature) { return { color: '#ff0000', opacity: 0.75, weight: 5 } } } } var layer = esri.featureLayer(item).addTo(map) layer.on('click', function(e) { // console.log(e) var str = '<div style="font-size: 14px;width:200px;">' + '<div style="font-size: 14px;margin-bottom: 8px;">' + '<div>' + e.layer.feature.properties.小类名称 + '</div></div>' + '<div style="padding-bottom: 4px"><col style="padding-right: 5px">大类:</col>' + e.layer.feature.properties.大类名称 + '</div>' + '<div style="padding-bottom: 4px"><col style="padding-right: 5px">小类:</col>' + e.layer.feature.properties.小类名称 + '</div>' + '<div style="padding-bottom: 4px"><col style="padding-right: 5px">部件编码:</col>' + e.layer.feature.properties.编码 + '</div>' + '<div style="padding-bottom: 4px"><col style="padding-right: 5px">权属单位:</col>' + e.layer.feature.properties.权属单位 + '</div>' + '<div style="padding-bottom: 4px"><col style="padding-right: 5px">详细地址:</col>' + e.layer.feature.properties.详细地址 + '</div>' + '<div>' var popup = L.popup().setContent(str) e.layer.dragging._marker.bindPopup(popup, { minWidth: 200 }).openPopup() // var id = e.layer.feature.properties.FID }) this.parts.push(layer) } this.map.on('pm:create', e => { // console.log(e) this.bounds = e.layer._bounds this.search() }) this.map.setZoom(15) }, handleCurrentChange(val) { this.offset = val var num = 5 * val >= this.searchlist.length ? this.searchlist.length : 5 * val this.showlist = this.searchlist.slice(5 * (val - 1), num) this.drawIcon() } } } </script> <style rel="stylesheet/scss" lang="scss" scoped> /deep/ .el-input-group__append, .el-input-group__prepend { background-color: #409eff !important; border: 1px solid #409eff !important; } /*/deep/ .leaflet-touch .leaflet-control-layers, /deep/ .leaflet-touch .leaflet-bar {*/ /*!*border: 2px solid rgba(0,0,0,0.2);*!*/ /*!*background-clip: padding-box;*!*/ /*position: absolute !important;*/ /*right: 300px !important;*/ /*top: 10px;*/ /*}*/ $tableTitleHeight:35px; .leaflet_container{ width: 100%; height: 84vh; } .search-total{ background-color: white; width: 300px;height: 35px; margin-top: 6px;border: 1px solid #DCDFE6; padding-left: 15px;color: #409eff; padding-top: 8px; font-size: 13px; border-radius:3px; } .draw-icon{ background-color: white; width: 100px;height: 40px; border: 1px solid #DCDFE6; border-radius:4px; } .table{ width: 300px;margin-top: 3px; border: 1px solid #DCDFE6; border-radius:3px; /deep/ .el-table th.is-leaf, /deep/ .el-table td { border-bottom: 1px solid white !important; } /deep/ .el-table--group::after, .el-table--border::after, .el-table::before { background-color: white !important; } .table-item{ padding: 5px; margin-top: 2px; margin-bottom: 1px; -moz-box-shadow: 0px 1px 3px #d9d9d9; /* 老的 Firefox */ box-shadow: 0px 1px 3px #d9d9d9; .item-icon{ width: 30px; height: 30px; background-size: contain; background-image: url("../../assets/global_images/point.png"); color: white; text-align: center; margin-top: 10px; margin-left: 5px; padding-top: 2px; } } } .top_title{ height: 40px; font-size: 18px; border: 1px solid #b5b5b5; padding-top: 10px; } .title{ height: 40px; width: 320px; padding-top: 10px; padding-left: 5px; z-index: 100000; background-color: rgba(255, 255, 255, 0.91); } .titletext{ text-align: center; font-size: 15px; } .titlenumtext{ text-align: center; font-size: 19px; } .list{ text-align:center; width: 500px; height: 40px; z-index: 10000; position: absolute; right:20px; top:20px; } .btn_bottom{ text-align:center; width: 100%; height:70px; z-index: 1000; position: fixed; bottom: 0; left: 0;right:0; } .table-name{ position:relative; width: 100px; top:20px; margin:-10px auto; //外面的div高度的一半 z-index: 100001; } .right-card{ margin-top: 20px;position: absolute;right:50px;z-index: 100000;width: 130px; } .table-title{ background-color:rgba(243, 243, 243, 1); height: $tableTitleHeight; .title-header{ line-height:$tableTitleHeight; color: #606266; font-size: 15px; i{ margin-left: 5px; margin-right: 5px; } } } </style>