<!-- Description: 闸井监测-地图 Author: 李亚光 Date: 2023-07-08 --> <script lang="ts" setup name="WellMap"> import detailInfo from './detailInfoDialog.vue' import AMap from '@/components/map/index.vue' const $props = defineProps({ height: { type: Number, default: 0, }, // 点位数据 data: { type: Array, default: () => ([]), }, // 管线数据 pipe: { type: Array, default: () => ([]), }, }) // 地图实例 const mapRef = ref() const publicPath = window.location.href.split('#')[0] // console.log(publicPath, 'publicPath') // 展示图例数据 const legendShowData = ref(['管网哨兵', '智能警示桩']) // 地图图例数据 const legendData = ref([ { name: '管网哨兵', url: `${publicPath}/image/pipeline/地埋式哨兵-正常.png`, value: '管网哨兵', }, { name: '智能警示桩', url: `${publicPath}/image/pipeline/警示桩-正常.png`, value: '智能警示桩', }, // { // name: '离线', // url: `${publicPath}/image/station/场站-离线.png`, // value: '3', // }, ]) // 控制图例 const clickLegend = (type: string) => { if (legendShowData.value.includes(type)) { legendShowData.value = legendShowData.value.filter((item: string) => item !== type) } else { legendShowData.value.push(type) } resetDraw() } // 初次加载标识 const pageIsFirst = ref(true) // 绘制标记点 const drawMarker = () => { const style = [ { url: `${publicPath}/image/pipeline/地埋式哨兵-离线.png`, // 图标地址 anchor: new mapRef.value.AMap.Pixel(4, 4), // 图标显示位置偏移量,基准点为图标左上角 size: new mapRef.value.AMap.Size(20, 20), // 图标的尺寸 zIndex: 99, // 每种样式图标的叠加顺序,数字越大越靠前 }, { url: `${publicPath}/image/pipeline/地埋式哨兵-正常.png`, // 图标地址 anchor: new mapRef.value.AMap.Pixel(4, 4), // 图标显示位置偏移量,基准点为图标左上角 size: new mapRef.value.AMap.Size(20, 20), // 图标的尺寸 zIndex: 99, // 每种样式图标的叠加顺序,数字越大越靠前 }, { url: `${publicPath}/image/pipeline/地埋式哨兵-异常.png`, // 图标地址 anchor: new mapRef.value.AMap.Pixel(4, 4), // 图标显示位置偏移量,基准点为图标左上角 size: new mapRef.value.AMap.Size(20, 20), // 图标的尺寸 zIndex: 99, // 每种样式图标的叠加顺序,数字越大越靠前 }, { url: `${publicPath}/image/pipeline/警示桩-离线.png`, // 图标地址 anchor: new mapRef.value.AMap.Pixel(4, 4), // 图标显示位置偏移量,基准点为图标左上角 size: new mapRef.value.AMap.Size(20, 20), // 图标的尺寸 zIndex: 99, // 每种样式图标的叠加顺序,数字越大越靠前 }, { url: `${publicPath}/image/pipeline/警示桩-正常.png`, // 图标地址 anchor: new mapRef.value.AMap.Pixel(4, 4), // 图标显示位置偏移量,基准点为图标左上角 size: new mapRef.value.AMap.Size(20, 20), // 图标的尺寸 zIndex: 99, // 每种样式图标的叠加顺序,数字越大越靠前 }, { url: `${publicPath}/image/pipeline/警示桩-异常.png`, // 图标地址 anchor: new mapRef.value.AMap.Pixel(4, 4), // 图标显示位置偏移量,基准点为图标左上角 size: new mapRef.value.AMap.Size(20, 20), // 图标的尺寸 zIndex: 99, // 每种样式图标的叠加顺序,数字越大越靠前 }, // { // url: `${publicPath}/image/pipeline/场站-离线.png`, // 图标地址 // anchor: new mapRef.value.AMap.Pixel(4, 4), // 图标显示位置偏移量,基准点为图标左上角 // size: new mapRef.value.AMap.Size(20, 20), // 图标的尺寸 // zIndex: 99, // 每种样式图标的叠加顺序,数字越大越靠前 // }, ] const styleDict = { '管网哨兵-0': 0, '管网哨兵-1': 1, '管网哨兵-2': 2, '智能警示桩-0': 3, '智能警示桩-1': 4, '智能警示桩-2': 5, } as { [key: string]: number } const data = $props.data.filter((item: any) => legendShowData.value.includes(item.deviceTypeName)).filter((item: any) => item.lng && item.lat && item.deviceTypeName && item.status).map((item: any) => ({ lnglat: [item.lng, item.lat], name: item.deviceTypeName, style: styleDict[`${item.deviceTypeName}-${item.status}`] || 0, id: item.deviceCode, row: item, })) console.log(data, '绘制标记点') mapRef.value.addMassMarks({ path: data, zIndex: 111, zooms: [3, 20], style, }) if (pageIsFirst.value) { mapRef.value.map.setCenter([116.397428, 39.90923]) } else { mapRef.value.map.setFitView() } mapRef.value.map.setZoom(10.5) } // 绘制线 const drawLine = () => { const data = $props.pipe.filter((item: any) => item.endLat && item.endLng && item.startLng && item.startLat && item.pipeCode) console.log(data, '准备绘制线') data.forEach((item: any) => { mapRef.value.addPolyline({ path: [[item.startLng, item.startLat], [item.endLng, item.endLat]], style: { strokeColor: '#E80D0D', strokeWeight: 2, strokeStyle: 'solid', zIndex: 95, }, }) }) } // 点标记弹窗 const detail = ref() const detailRef = ref() const massMarksClick = (data: any) => { mapRef.value.map.setZoom(10.5) // 定义弹窗 detail.value = new mapRef.value.AMap.InfoWindow({ closeWhenClickMap: true, // 是否在鼠标点击地图后关闭信息窗体 autoMove: true, // 是否自动调整窗体到视野内 isCustom: true, // 自定义信息窗体 content: detailRef.value.$el, // 窗体内容(vue组件) offset: new mapRef.value.AMap.Pixel(9, -5), // 偏移 }) // 打开信息窗口 detail.value.open(data.map, data.event.data.lnglat) // 初始化信息窗口 detailRef.value.initDialog({ overlay: data.event.target, infoWindow: detail.value, info: data.event.data, map: mapRef.value.map, }) setTimeout(() => { // mapRef.value.map.setZoom(14) // mapRef.value.map.setFitView() mapRef.value.map.setCenter(data.event.data.lnglat) }) // 关联的管线高亮 const line = $props.pipe.filter((item: any) => item.pipeCode === data.event.data.row.pipeCode) console.log(line, 'line') if (line.length) { if (!mapRef.value.lineAllList.length) { return } const link = mapRef.value.lineAllList.filter((item: any) => line.filter((citem: any) => [[citem.startLng, citem.startLat], [citem.endLng, citem.endLat]].join() === item.$x.join()).length) console.log(link, 'link') if (link.length) { link.forEach((element: any) => { element.setOptions({ strokeColor: '#34A0E8', strokeWeight: 4, }) }) } } } // 打开信息窗体 const openInfoDetail = (data: any) => { mapRef.value.map.setZoom(10.5) // 定义弹窗 detail.value = new mapRef.value.AMap.InfoWindow({ closeWhenClickMap: true, // 是否在鼠标点击地图后关闭信息窗体 autoMove: true, // 是否自动调整窗体到视野内 isCustom: true, // 自定义信息窗体 content: detailRef.value.$el, // 窗体内容(vue组件) offset: new mapRef.value.AMap.Pixel(9, -5), // 偏移 }) // 打开信息窗口 setTimeout(() => { detail.value.open(mapRef.value.map, data.lnglat) // 初始化信息窗口 detailRef.value.initDialog({ infoWindow: detail.value, info: data, map: mapRef.value.map, }) mapRef.value.map.setCenter(data.lnglat) }) } // 重置标记点 function resetDraw() { mapRef.value.removeMassMarks() if (detailRef.value) { detailRef.value.close() } if ($props.data) { // 清空标记点重新绘制 drawMarker() } } // 重置线 function resetDrawLine() { mapRef.value.removePolyline() if (detailRef.value) { detailRef.value.close() } if ($props.pipe) { // 清空闲重新绘制 drawLine() } } // 地图绘制完毕 const completeMap = () => { console.log('地图绘制完毕') // 绘制海量点 resetDraw() clickLegend('智能警示桩') setTimeout(() => { clickLegend('智能警示桩') }) // 绘制线 resetDrawLine() setTimeout(() => { pageIsFirst.value = false }, 2000) } defineExpose({ openInfoDetail, drawMarker, resetDraw, drawLine, resetDrawLine, mapRef }) </script> <template> <div :style="`height: ${$props.height}px`" class="map-container"> <!-- 设备信息窗体 --> <detail-info ref="detailRef" /> <!-- 地图 --> <a-map ref="mapRef" @complete="completeMap" @massMarksClick="massMarksClick" /> <!-- 图例 --> <div class="legend"> <div v-for="item in legendData" :key="item.value" class="legend-item" @click="clickLegend(item.value)"> <img v-show="legendShowData.includes(item.value)" class="img" :src="item.url"> <span v-show="!legendShowData.includes(item.value)" class="img" /> <span style="margin-left: 5px;">{{ item.name }}</span> </div> </div> </div> </template> <style lang="scss" scoped> .map-container { width: 100%; position: relative; } .legend { background: rgb(255 255 255 / 80%); position: absolute; z-index: 1; left: 15px; bottom: 10px; padding: 0 10px; border-radius: 3px; .legend-item { margin: 10px 0; // font-weight: 700; display: flex; align-items: center; .img { width: 20px; height: 20px; } &:hover { cursor: pointer; } } } </style>