Newer
Older
SpaceIntegration_front / src / components / map / Map.vue
liyaguang on 31 Oct 2023 7 KB feat(*): 首页巡检车统计面板
<!-- 地图 -->
<script lang="ts" name="Map" setup>
import { load } from '@amap/amap-jsapi-loader'
import infoDialog from './infoDialog.vue'
import useMapStore from '@/store/modules/map'
const props = defineProps({
  center: { // 地图中心点
    type: Array,
    default: () => ([116.26759100, 39.91563500]),
  },
  zoom: { // 地图显示的缩放级别
    type: Number,
    default: 17,
  },
  // 坐标点数组(包含左边点信息)
  // 例:[{alarmCode: "XJBJ202310300067",lat: "39.914083",log: "116.265872",icon: ""}]
  // 必须含有坐标点数据icon
  // point: {
  //   type: Array,
  //   default: () => ([] as any[]),
  // },
})
const mapInfo = useMapStore() // 地图信息
const isMap = ref(false) // 是否初始话完成
declare const window: any
const map = ref() // 地图实例
const AMapRef = ref<any>()
const infoWindow = ref() // 信息窗体
const windowInfoRef = ref() // 信息窗体实例
const markerList = ref<any[]>([]) // 标记点实例
const lineMarkerList = ref<any[]>([]) // 折线标记点实例
const lineList = ref<any>() // 标记点实例
const initMap = () => { // 初始化
  if (!window._AMapSecurityConfig) {
    // 安全码
    window._AMapSecurityConfig = {
      securityJsCode: mapInfo.amapSecurityCode,
    }
  }
  load({
    key: mapInfo.amapKey, // 秘钥
    version: '2.0', // api版本,2.0
  }).then((AMap: any) => {
    AMapRef.value = AMap
    map.value = new AMap.Map('container',
      {
        zoom: props.zoom, // 设置地图显示的缩放级别
        center: props.center, // 设置地图中心点坐标
        // layers: [new AMap.TileLayer.Satellite()],  //设置图层,可设置成包含一个或多个图层的数组
        // mapStyle: 'amap://styles/whitesmoke',  //设置地图的显示样式
        viewMode: '2D', // 设置地图模式
      })
    let toolbar
    AMap.plugin('AMap.ToolBar', () => { // 异步加载插件
      toolbar = new AMap.ToolBar() // 缩放工具条实例化
      map.value.addControl(toolbar)
    })
    // if (props.center?.length) {
    //   const marker = new AMap.Marker({ // 标注
    //     position: props.center, // 位置
    //   })
    //   map.value.add(marker) // 标注添加到地图
    // }
    isMap.value = true
  })
}
// 根据经纬度查询位置信息
// const searchPosition = (position: any[]) => {
//   new (AMapRef.value).plugin('AMap.Geocoder', () => {
//     const geocoder = new map.Geocoder({
//       // city 指定进行编码查询的城市,支持传入城市名、adcode 和 citycode
//       city: '028', // 成都
//     })
//     geocoder.getAddress(position, (status, result) => {
//       if (status === 'complete' && result.info === 'OK') {
//         // result为对应的地理位置详细信息
//         this.place = result.regeocode.formattedAddress
//         // this.place为返回的具体地理位置信息,里面无法使用return回来!
//       }
//     })
//   })
// }
onMounted(() => {
  if (!map.value) {
    console.log('地图初始化')
    initMap()
  }
})
// 绘制标记点
const drawPonit = (arr: any[]) => {
  // arr 为标记点数组信息数据
  // 坐标点数组(包含左边点信息)
  // 例:[{alarmCode: "XJBJ202310300067",lat: "39.914083",log: "116.265872",icon: ""}]
  // 必须含有坐标点数据icon

  // 加工标记点数据
  const pointArr = arr.map((item: any) => ([Number(item.lng), Number(item.lat)]))
  // if (pointArr.length) {
  //   map.value.setCenter(pointArr[0])
  // }
  map.value.setFitView()
  const AMap = AMapRef.value
  // 标记点绘制
  for (let i = 0; i < arr.length; i++) {
    // 自定义icon
    const icon = new AMap.Icon({
      size: new AMap.Size(36, 36), // 图标尺寸
      image: arr[i].icon, // Icon的图像
      imageSize: new AMap.Size(24, 30), // 根据所设置的大小拉伸或压缩图片
      imageOffset: new AMap.Pixel(0, 0), // 图像相对展示区域的偏移量,适于雪碧图等
    })
    // 标记点
    const marker = new AMap.Marker({
      // zooms: [16, 20], // 缩放
      position: pointArr[i], // 经纬度对象,也可以是经纬度构成的一维数组[116.39, 39.9]
      map: map.value,
      icon,
      offset: new AMap.Pixel(3, -30),
    })
    markerList.value.push(marker)
    // 信息窗体
    infoWindow.value = new AMap.InfoWindow({
      isCustom: true, // 自定义信息窗体
      content: windowInfoRef.value.$el, // 窗体内容(vue组件)
      offset: new AMap.Pixel(9, -5), // 偏移
    })
    // 信息窗体点击事件
    marker.on('click', (e) => {
      // 打开信息窗口
      infoWindow.value.open(map.value, e.lnglat)
      // 初始化信息窗口
      windowInfoRef.value.initialize({
        overlay: e.target,
        infoWindow: infoWindow.value,
        // 标记点详细信息
        info: arr[i],
      })
    })

    // 将标记点添加到地图
    map.value.add([marker])
  }
}
// 绘制折线(轨迹)
const drawLine = (arr: any[]) => {
  // 先绘制点
  // 加工标记点数据
  const pointArr = arr.map((item: any) => ([Number(item.lng), Number(item.lat)]))
  const AMap = AMapRef.value

  // 标记点绘制
  for (let i = 0; i < arr.length; i++) {
    // 自定义标记点
    const markerContent = ''
        + '<div class="content-marker">'
        + `${i + 1}`
        + '</div>'
    // 标记点
    const marker = new AMap.Marker({
      // zooms: [16, 20], // 缩放
      position: pointArr[i], // 经纬度对象,也可以是经纬度构成的一维数组[116.39, 39.9]
      map: map.value,
      content: markerContent,
      offset: new AMap.Pixel(0, 0),
    })
    lineMarkerList.value.push(marker)
    // 信息窗体
    infoWindow.value = new AMap.InfoWindow({
      isCustom: true, // 自定义信息窗体
      content: windowInfoRef.value.$el, // 窗体内容(vue组件)
      offset: new AMap.Pixel(9, -5), // 偏移
    })
    // 信息窗体点击事件
    marker.on('click', (e) => {
      // 打开信息窗口
      infoWindow.value.open(map.value, e.lnglat)
      // 初始化信息窗口
      windowInfoRef.value.initialize({
        overlay: e.target,
        infoWindow: infoWindow.value,
        // 标记点详细信息
        info: arr[i],
      })
    })
    // 将标记点添加到地图
    map.value.add([marker])
  }
  // 折线绘制
  const polyline = new AMap.Polyline({
    path: pointArr,
    // isOutline: true,
    strokeColor: '#ff0',
    strokeOpacity: 1,
    strokeWeight: 4,
    // 折线样式还支持 'dashed'
    // strokeStyle: 'dashed',
    // strokeStyle是dashed时有效
    strokeDasharray: [10, 3],
    lineJoin: 'round',
    showDir: true,
    // lineCap: 'square',
    lineCap: 'round',
    zIndex: 50,
    // zooms: [16, 20],

  })
  lineList.value = polyline
  polyline.setMap(map.value)
  map.value.add(polyline)
  map.value.setFitView()
}
// 清空所有绘制
const clearDraw = () => {
  map.value.setFitView()
  map.value.clearMap()
}
// 清空标记点
const clearPonit = () => {
  map.value.setFitView()
  if (markerList.value.length) {
    map.value.remove(markerList.value)
    markerList.value = []
  }
}
// 清空折线(轨迹)
const clearLine = () => {
  map.value.setFitView()
  // 先清空折线的标记点
  if (lineMarkerList.value.length) {
    map.value.remove(lineMarkerList.value)
    lineMarkerList.value = []
  }
  // 再清空折线
  if (lineList.value) {
    map.value.remove(lineList.value)
    lineList.value = ''
  }
}

defineExpose({ drawPonit, clearDraw, isMap, drawLine, clearPonit, clearLine })
</script>

<template>
  <div id="container" style="width: 100%; height: 100%;" />
  <!-- <div class="input-item">
    <input id="toolbar" type="checkbox" onclick="toggleToolBar(this)">工具条
  </div> -->
  <!-- 信息窗体 -->
  <info-dialog ref="windowInfoRef" />
</template>

<style lang="scss" scope>
.content-marker {
  border-radius: 50%;
  width: 16px;
  height: 16px;
  background-color: rgba(#ff0, 0.8);
  border: 1px solid #ccc;
  line-height: 16px;
  text-align: center;
  font-size: 18px;
  font-weight: 700;
}
</style>