Newer
Older
smartwell_front / src / components / map / index.vue
<!--
  Description: 高德地图
  Author: 李亚光
  Date: 2023-04-21
 -->
<script lang="ts" setup name="GuadMap">
import AMapLoader from '@amap/amap-jsapi-loader'
import { styleType } from 'element-plus/es/components/table-v2/src/common'

const $props = defineProps({
  // 初始图层 normal satellite
  layer: {
    type: String,
    default: 'normal',
  },
  center: {
    type: Array,
    default: () => ([116.397428, 39.90923]),
  },
  zoom: {
    type: Number,
    default: 9,
  },
})
const $emits = defineEmits(['complete', 'marke', 'markerClick', 'lineClick'])
const loading = ref(true)
// 设置安全密钥
window._AMapSecurityConfig = {
  securityJsCode: localStorage.getItem('securityJsCode')!, // 后期需替换
}
// 地图实例
const map = shallowRef()
const AMap = ref()
// 图层
const layer = ref()
// 图层标识
const layerFlag = ref('normal')
// const publicPath = import.meta.env.BASE_URL
// console.log(publicPath, 'publicPath')
// -------------------------------------初始化地图--------------------------------------------------
const initMap = () => {
  AMapLoader.load({
    key: localStorage.getItem('JsKey')!, // 后期需替换
    version: '2.0', // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
    plugins: ['AMap.Scale', 'AMap.MouseTool'], // 需要使用的的插件列表,如比例尺'AMap.Scale'等
  })
    .then((AMap1: any) => {
      AMap.value = AMap1
      // 初始化地图
      map.value = new AMap1.Map('map', {
        viewMode: '3D', //  是否为3D地图模式
        zoom: $props.zoom, // 初始化地图级别
        resizeEnable: true,
        center: $props.center,
      })
      // 图层
      if ($props.layer === 'satellite') {
        // 卫星图层
        layer.value = new AMap1.TileLayer.Satellite()
        map.value.addLayer(layer.value)
        map.value.setFeatures(['bg', 'building'])
        layerFlag.value = 'satellite'
      }
      // 地图图块加载完成后触发
      map.value.on('complete', () => {
        //  修改loading状态
        console.log('地图加载完成')
        $emits('complete')
        loading.value = false
      })
      // 地图绑定右击事件
      map.value.on('mousedown', clickHandler)
    })
    .catch((e) => {
      console.log('地图加载失败')
    })
}
// ------------------------------------------------------------------------------------------------
function clickHandler(e) {
  const location = [e.lnglat.getLng(), e.lnglat.getLat()]
  if (event.button === 2) {
    console.log('当前点击坐标为:   ', location)
  }
}
// -------------------------------------切换图层----------------------------------------------------
const changeLayerGrop = () => {
  if (layerFlag.value === 'normal') {
    layer.value = new AMap.value.TileLayer.Satellite()
    map.value.addLayer(layer.value)
    map.value.setFeatures(['bg', 'building'])
    layerFlag.value = 'satellite'
  }
  else {
    map.value.removeLayer(layer.value)
    layerFlag.value = 'normal'
  }
}
// ------------------------------------------------------------------------------------------------
// -------------------------------------多边形操作--------------------------------------------------
// 多边形数组
const polygonAllList = ref<any>([])
// 绘制多边形
function addPolygon(data: any[], style = {
  name: '',
  fillColor: '#ccebc5', // //多边形填充颜色
  strokeOpacity: 1, // 多边形填充透明度
  fillOpacity: 0.3, // 多边形填充透明度
  strokeColor: '#2b8cbe', // 线条颜色
  strokeWeight: 2, // 轮廓线宽度
  strokeStyle: 'dashed',
  strokeDasharray: [5, 5],
  activeFillColor: '#7bccc4', // 鼠标进入多边形的激活颜色
  dbclickSetCenter: false, // 双击多边形自动放大切切换中心试图
  dbclickCenter: [], // 中心坐标
}) {
  const polygon = new AMap.value.Polygon({
    path: data, // 边界数据
    fillColor: style.fillColor,
    strokeOpacity: style.strokeOpacity,
    fillOpacity: style.fillOpacity,
    strokeColor: style.strokeColor,
    strokeWeight: style.strokeWeight,
    strokeStyle: style.strokeStyle,
    strokeDasharray: style.strokeDasharray,
  })
  polygonAllList.value.push(polygon)
  polygon.on('mouseover', () => {
    polygon.setOptions({
      fillOpacity: style.fillOpacity + 0.2,
      fillColor: style.activeFillColor,
    })
  })
  polygon.on('mouseout', () => {
    polygon.setOptions({
      fillOpacity: style.fillOpacity,
      fillColor: style.fillColor,
    })
  })
  polygon.on('mousedown', clickHandler)
  if (style.dbclickSetCenter) {
    polygon.on('dblclick', () => {
      console.log(`当前点击的是${style.name}`)
      map.value.setCenter(style.dbclickCenter)
      map.value.setZoom(9.6)
    })
  }
  map.value.add(polygon)
}
// 移除多边形
const removePolygon = () => {
  polygonAllList.value.forEach((item: any) => {
    item.setMap(null)
  })
  polygonAllList.value = []
  console.log('清除绘制的多边形')
}
// ------------------------------------------------------------------------------------------------

// -------------------------------------标记本文操作--------------------------------------------------
// 标记文本数组
const textAllList = ref<any>([])
// 添加标记文字
function addText(data: any, style = {
  /**
   * data 示例
   *  text: 文本内容
   *  position: 位置
   */
  // 'padding': '.75rem 1.25rem',
  // 'width': '15rem',
  // 'border-width': 0,
  // 'text-align': 'center',
  'font-size': '18px',
  'color': 'white',
  'background-color': 'transparent',
  'border-color': 'transparent',
}) {
  // 创建纯文本标记
  var Text = new AMap.value.Text({
    text: data.text, // 文本内容
    anchor: 'center', // 设置文本标记锚点
    draggable: false, // 是否可拖拽
    cursor: '', // 鼠标样式
    angle: 0, // 旋转角度
    style, // 文本样式
    position: data.position, // 点标记在地图上显示的位置
  })
  textAllList.value.push(Text)
  Text.setMap(map.value)
}
// 移除标记文字
const removeText = () => {
  textAllList.value.forEach((item: any) => {
    item.setMap(null)
  })
  textAllList.value = []
}
// ------------------------------------------------------------------------------------------------

// -------------------------------------点标记操作--------------------------------------------------
// 点标记(一般点标记)数组
const markerAllList = ref<any>([])
// 添加点标记 (一般点标记)
const addMarker = (data: any) => {
  /**
   * data 示例
   *  position: 位置
   *  content: 标记点内容 html
   *  label: 文本标记
   */
  var marker = new AMap.value.Marker({
    position: data.position,
    // 将 html 传给 content
    content: data.content,
    // 以 icon 的 [center bottom] 为原点
    offset: new AMap.value.Pixel(-13, -30),
  })
  markerAllList.value.push(marker)
  // markers的信息窗体
  marker.on('click', (e: any) => {
    console.log('标记点')
    $emits('markerClick', { event: e, map: map.value, data, marker })
  })
  // 标记点文本标记
  marker.setLabel({
    offset: new AMap.value.Pixel(0, -5), // 设置文本标注偏移量
    content: `<div style="color:white;font-size:15px;">${data.label}</div>`, // 设置文本标注内容
    direction: 'top-center', // 设置文本标注方位
  })
  // 将 markers 添加到地图
  map.value.add(marker)
}
// 移除点标记 (一般点标记)
const removeMarker = () => {
  markerAllList.value.forEach((item: any) => {
    item.setMap(null)
  })
  markerAllList.value = []
}
// ------------------------------------------------------------------------------------------------

// -------------------------------------绘线操作--------------------------------------------------
// 折线数组
const lineAllList = ref<any[]>([])
// 添加折线
const addPolyline = (data: any) => {
  /**
   * data
   * path: 折线点位数据  [[],[],[]]
   * style 折线样式
   *    style样式参考
   *      isOutline: true,
          outlineColor: '#ffeeff',
          borderWeight: 3,
          strokeColor: "#3366FF",
          strokeOpacity: 1,
          strokeWeight: 6,
          // 折线样式还支持 'dashed'
          strokeStyle: "dashed",
          // strokeStyle是dashed时有效
          strokeDasharray: [15, 5],
         lineJoin: 'round',
         lineCap: 'round',
         zIndex: 50,
   */
  var polyline = new AMap.value.Polyline({
    path: data.path,
    ...data.style,
  })
  lineAllList.value.push(polyline)
  polyline.on('click', (e) => {
    console.log('点击了线')
    $emits('lineClick', { event: e, map: map.value, data, polyline })
  })
  map.value.add([polyline])
}
// 移除折线
const removePolyline = () => {
  lineAllList.value.forEach((item: any) => {
    item.setMap(null)
  })
  lineAllList.value = []
}
// ------------------------------------------------------------------------------------------------
onMounted(() => {
  loading.value = true
  initMap()
})
onBeforeUnmount(() => {
  if (map.value) {
    map.value.destroy()
  }
})
defineExpose({
  changeLayerGrop, // 切换图层
  layerFlag, // 当前图层标识
  addPolygon, // 绘制多边形区域
  removePolygon, // 移除多边形
  addText, // 添加标记文字
  removeText, // 移除标记文字
  addMarker, // 添加点标记 (一般点标记)
  removeMarker, // 移除点标记 (一般点标记)
  addPolyline, // 添加折线
  removePolyline, // 移除折线
})
</script>

<template>
  <div class="container">
    <!-- 地图 -->
    <div id="map" v-loading="loading" />
  </div>
</template>

<style lang="scss" scoped>
.container {
  height: 100%;
  width: 100%;
}

::v-deep(.amap-marker-label) {
  background-color: transparent;
  border: none;
}

#map {
  overflow: hidden;
  width: 100%;
  height: 100%;
  margin: 0;
  font-family: "微软雅黑";
}
</style>

<style>
/* 隐藏高德logo  */
.amap-logo {
  display: none !important;
}

/* 隐藏高德版权  */
.amap-copyright {
  display: none !important;
}

.img-map-marker {
  width: 20px;
  height: 20px;
}
</style>