Newer
Older
robot_dog_patrol_front / src / views / home / dashboard / components / controlMap.vue
lyg on 20 Sep 9 KB 导入导出
<!--
  Description: 综合大屏-布控地图
  Author: 李亚光
  Date: 2024-07-18
 -->
<script lang="ts" setup>
import baseOverView from '../fullScreen-components/baseOverView.vue'
import { mapData } from './mapData'
import detailInfo from './detailInfoDialog.vue'
import AMap from '@/components/map/index.vue'
// 地图实例
const mapRef = ref()
const zoomStatus = ref('') // 当前缩放状态
// 地图挂载完毕执行
const drawBj = () => {
  const style = {
    fillColor: 'transparent',
    strokeOpacity: 1,
    fillOpacity: 0.3,
    strokeColor: '#2b8cbe',
    strokeWeight: 2,
    strokeStyle: 'solid',
    strokeDasharray: [5, 5],
    activeFillColor: '#3CA4D2',
    dbclickSetCenter: true,
    zIndex: 1,
  }

  mapData.forEach((item: any) => {
    // 绘制北京各个区边界
    mapRef.value.addPolygon(item.data, {
      ...style,
      name: item.name,
      dbclickCenter: item.center,
    })
  })
}
// 图例展示
const legend = ref(['点', '线'])
// 双击多边形(行政区或九五示范区)掉起弹窗
const detail = ref()
const detailRef = ref()
const polygonClick = (data: any) => {
  if (zoomStatus.value === 'hidden') { return }
  console.log(data, '双击行政区')
  data.map.setCenter(data.style.dbclickCenter)
  data.map.setZoom(9.6)
  // 定义弹窗
  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.lnglat)
  // 初始化信息窗口
  detailRef.value.initDialog({
    overlay: data.event.target,
    infoWindow: detail.value,
    info: data.style,
    flag: 'district', // 行政区或95示范区
  })
}

// 绘制管线
const drawLine = () => {
  // 模拟海量点数据
  const data = [
    [115.918546, 39.812809],
    [115.929436, 39.814813],
    [115.932418, 39.815577],
    [115.934778, 39.816881],
    [115.939913, 39.817421],
    [115.942935, 39.817867],
    [115.946041, 39.818535],
    [115.946609, 39.819261],
    [115.947517, 39.820288],
    [115.948852, 39.820757],
    [115.949681, 39.821012],
    [115.949213, 39.821635],
    [115.949137, 39.821666],
    [115.948514, 39.821778],
    [115.94831, 39.82186],
  ]
  mapRef.value.addPolyline({
    path: data,
    style: {
      strokeColor: '#BAAF04',
      strokeWeight: 4,
      strokeStyle: 'solid',
      zIndex: 95,
      zoomLevels: [10.5, 18],
    },
  })
  // 判断图例设置(没有显示的直接就隐藏)
  if (!legend.value.includes('线')) {
    mapRef.value.lineAllList.forEach((line: any) => {
      line.hide()
    })
  }
}
// 点击管线(选中管线高亮)
const lineClick = (data: any) => {
  console.log(data, '点击管线(选中管线高亮)')
  if (data.polyline.getOptions().strokeWeight === 4.5) {
    // 取消高亮
    data.polyline.setOptions({
      strokeColor: '#BAAF04',
      strokeWeight: 4,
    })
  }
  else {
    // 高亮
    data.polyline.setOptions({
      strokeColor: '#EAFA03',
      strokeWeight: 4.5,
    })
  }
}
// 绘制阀门,调压站等点标记
const drawMarker = () => {
  const style = [
    {
      url: 'https://a.amap.com/jsapi_demos/static/images/mass0.png', // 图标地址
      anchor: new mapRef.value.AMap.Pixel(4, 4), // 图标显示位置偏移量,基准点为图标左上角
      size: new mapRef.value.AMap.Size(7, 7), // 图标的尺寸
      zIndex: 99, // 每种样式图标的叠加顺序,数字越大越靠前
    },
    {
      url: 'https://a.amap.com/jsapi_demos/static/images/mass1.png',
      anchor: new mapRef.value.AMap.Pixel(4, 4),
      size: new mapRef.value.AMap.Size(11, 11),
      zIndex: 99,
    },
  ]
  const data = [
    {
      lnglat: [115.94831, 39.82186], // 经纬度
      name: '天安门',
      style: 1, // 该数据的取值为样式数组对应的对象索引
    },
    {
      lnglat: [115.932418, 39.815577],
      name: '南锣鼓巷',
      style: 2,
    },
  ]
  mapRef.value.addMassMarks({
    path: data,
    zIndex: 111,
    zooms: [10.5, 20],
    style,
  })
  // 判断图例设置(没有显示的直接就隐藏)
  if (!legend.value.includes('点')) {
    mapRef.value.massMarksAllList.forEach((line: any) => {
      line.hide()
    })
  }
}
// 阀门,调压站等点标记点击
const massMarksClick = (data: any) => {
  console.log(data, '阀门,调压站等点标记点击')
  // 定义弹窗
  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), // 偏移
  })
  console.log(detail.value, 'detail.value 点')
  // 打开信息窗口
  console.log(data.event.data.lnglat, 'data.event.data.lnglat')
  detail.value.open(data.map, data.event.data.lnglat)
  // 初始化信息窗口
  detailRef.value.initDialog({
    overlay: data.event.target,
    infoWindow: detail.value,
    info: data.event.data,
    // flag: 'valve', // 阀门
    flag: 'district', // 阀门
  })
}

// 监听地图缩放
watch(() => mapRef.value?.zoom, (newVal) => {
  if (!newVal) { return }
  // 10.5作为临界点 隐藏行政区hover  显示设备以及管线
  if (newVal >= 10.5) {
    if (zoomStatus.value === 'hidden') { return }
    // 隐藏行政区hover
    mapRef.value.polygonAllList.forEach((polygon: any) => {
      polygon.setOptions({
        fillOpacity: 0.3,
        fillColor: 'transparent',
      })
      polygon.on('mouseover', () => {
        polygon.setOptions({
          fillOpacity: 0.3,
          fillColor: 'transparent',
        })
      })
    })
    // 绘制管线
    drawLine()
    // 绘制阀门,调压站等点标记
    drawMarker()
    zoomStatus.value = 'hidden'
  }
  else {
    if (zoomStatus.value === 'show') { return }
    // 显示行政区hover
    mapRef.value.polygonAllList.forEach((polygon: any) => {
      polygon.on('mouseover', () => {
        polygon.setOptions({
          fillOpacity: 0.5,
          fillColor: '#3CA4D2',
        })
      })
    })
    // 移除管线
    mapRef.value.removePolyline()
    // 移除标记点
    mapRef.value.removePolyline()
    zoomStatus.value = 'show'
  }
})

// 点击图例,显示隐藏对应的点或线
const clickLegend = (data: { name: string; type: string }) => {
  if (legend.value.includes(data.name)) {
    //  隐藏
    legend.value = legend.value.filter((citem: string) => citem !== data.name)
    if (data.type === 'line') {
      mapRef.value.lineAllList.forEach((line: any) => {
        line.hide()
      })
    }
    else {
      mapRef.value.massMarksAllList.forEach((marker: any) => {
        marker.hide()
      })
    }
  }
  else {
    // 显示
    legend.value.push(data.name)
    if (data.type === 'line') {
      mapRef.value.lineAllList.forEach((line: any) => {
        console.log(line, 'line')
        line.show()
      })
    }
    else {
      mapRef.value.massMarksAllList.forEach((marker: any) => {
        marker.show()
      })
    }
  }
}
</script>

<template>
  <div class="full-container">
    <!-- 左侧 -->
    <div>
      <!-- 基本概况 -->
      <base-over-view />
    </div>
    <!-- 设备信息窗体 -->
    <detail-info ref="detailRef" />
    <!-- 地图 -->
    <a-map
      ref="mapRef" layer="dark" :zoom="9.2" :center="[116.372535, 40.213715]" @complete="drawBj"
      @polygonClick="polygonClick" @lineClick="lineClick" @massMarksClick="massMarksClick"
    />
    <!-- 图例 -->
    <div class="amap-legend">
      <div class="legend-item">
        <div class="icon" :class="legend.includes('点') ? '' : 'none'">
          图标
        </div>
        <div class="value" @click="clickLegend({ name: '点', type: 'marker' })">
          点
        </div>
      </div>
      <div class="legend-item">
        <div class="icon" :class="legend.includes('线') ? '' : 'none'">
          图标
        </div>
        <div class="value" @click="clickLegend({ name: '线', type: 'line' })">
          线
        </div>
      </div>
    </div>
  </div>
</template>

<style>
.full-container {
  width: 100%;
  height: 100vh;
}

.none {
  opacity: 0;
}

.amap-legend {
  position: fixed;
  bottom: 10px;
  left: 10px;
  background: rgb(68 66 66 / 60%);
  color: #fff;
  padding: 10px;

  .legend-item {
    display: flex;

    .value {
      &:hover {
        cursor: pointer;
      }
    }
  }
}

.close {
  width: 150px;
  height: 70px;
  position: fixed;
  top: 0;
  right: 0;

  /* background-color: antiquewhite; */
  &:hover {
    .icon {
      display: block;
    }
  }

  .icon {
    display: none;
    width: 50px;
    height: 50px;
    background: rgb(145 144 144 / 60%);
    border-radius: 50%;
    line-height: 50px;
    text-align: center;
    font-size: 18px;
    font-weight: 700;
    color: #ccc;
    margin: 10px auto;

    &:hover {
      cursor: pointer;
    }
  }
}
</style>