vue3百度地图

  • Post author:
  • Post category:vue



1.index.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <link rel="icon" href="/favicon.ico" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title></title>
  </head>
  <body>
    <div id="app"></div>
    <script type="module" src="/src/main.ts"></script>
  </body>
  <script>
    document.write(unescape("%3Cscript src='./config.local.js?_t=" + Math.random() + "' type='text/javascript'%3E%3C/script%3E"));
  </script>
  //添加AK
  <script type="text/javascript" src="https://api.map.baidu.com/api?v=3.0&ak=自己的ak"></script>
</html>


2.在component文件夹下新建自定义子组件map-baidu.vue

<template>
  <section class="map-baidu-box">
    <div ref="mapRef"></div>
  </section>
</template>

<script lang="ts" setup>
import darkJson from './json/dark-1.json';//地图背景

interface MarkIcon {
  url: string,
  size: [number, number],
}

interface MarkOption extends AnyObject {
  x: number,
  y: number,
  icon: MarkIcon,
}

const emit = defineEmits(['map-ready', 'map-click', 'mark-click']);

const props = withDefaults(
  defineProps<{
    zoom?: number, // 缩放大小
    point?: number[], // 展示的点位
    markOptions?: MarkOption[], // 标记的点位
    markTipTemplate?: Function, // 标记tip模板
  }>(),
  {
    point: () => [120.27009107213996, 30.19237475223979],
  }
);

const mapRef = ref();
const BMap = (window as any).BMap;

let mapInstance = null as any;
const markTooltip = document.createElement('div');

// 标记map
function setMapMark(markOption: MarkOption) {
  // 创建图标
  const myIcon = new BMap.Icon(
    markOption.icon.url,
    new BMap.Size(markOption.icon.size[0], markOption.icon.size[1])
  );
  // 设置mark坐标
  const pt = new BMap.Point(markOption.x, markOption.y);
  // 创建mark标注
  const marker = new BMap.Marker(pt, { icon: myIcon });
  // 将标注添加到地图
  mapInstance.addOverlay(marker);
  // 添加mark监听点击事件
  marker.addEventListener('click', function (e: any) {
    if (props.markTipTemplate) {
      const tooltip = props.markTipTemplate(markOption);
      markTooltip.remove();
      markTooltip.innerHTML = tooltip;
      e.target.Ec.appendChild(markTooltip);
      e.domEvent.preventDefault();
      e.domEvent.stopPropagation();
    }
    emit('mark-click', { e, markOption, mapInstance });
  });
}

// 更新map标点
function updateMapMark(marks: MarkOption[]) {
  marks.forEach(item => setMapMark(item));
}

// 更新map中心点位置和缩放大小
function updateMapPointAndZoom(point: number[], zoom: number = 14) {
  mapInstance.centerAndZoom(new BMap.Point(point[0], point[1]), zoom);
}

// 重置中心点位置和缩放大小
function resetMapPointAndZoom() {
  updateMapPointAndZoom(props.point, props.zoom);
}

onMounted(() => {
  mapInstance = new BMap.Map(mapRef.value);

  resetMapPointAndZoom();

  mapInstance.enableScrollWheelZoom(true);
  mapInstance.setMapStyleV2({ styleJson: darkJson });

  mapInstance.addEventListener('click', function (e: any) {
    markTooltip.remove();
    emit('map-click', { e, mapInstance });
    // markMap(map, [e.point.lng, e.point.lat], 1);
    console.log('点击的经纬度:' + e.point.lng + ',' + e.point.lat);
  });

  updateMapMark(props.markOptions || []);

  emit('map-ready', mapInstance);
});

watch(
  () => props.markOptions,
  async (value) => {
    await nextTick();
    updateMapMark(value || []);
  },
  { deep: true }
);

defineExpose({ mapInstance, setMapMark, updateMapMark, updateMapPointAndZoom });
</script>

<style lang="scss">
.map-baidu-box {
  height: 100%;
  width: 100%;
  
  > div {
    width: 100%;
    height: 100%;
  }

  .anchorBL a {
    display: none;
  }
}
</style>


3.父组件调用

<template>
	<div class="map">
      <map-baidu
        :point="mapState.point"
        :mark-options="mapState.markOptions"
        :mark-tip-template="markTipTemplate"
      />
    </div>
</template>
<script lang="ts" setup>
import mapMarkIcon from "@/assets/img/monitor/map-position.png";

//#region 地图

// 点位图标
const markIcon = { url: mapMarkIcon, size: [44 * 0.6, 53 * 0.6] };

// map配置项
const mapState = reactive<any>({
  point: [120.27756497398268, 30.189003846530078],
  markOptions: [
    { id: 1, x: 120.24307004239976, y: 30.209042695252734, icon: markIcon },
    { id: 2, x: 120.26103615259932, y: 30.207794267330275, icon: markIcon },
    { id: 3, x: 120.25543072621706, y: 30.193061609836626, icon: markIcon },
    { id: 4, x: 120.32743889589689, y: 30.17470509958105, icon: markIcon },
    { id: 5, x: 120.29538735530087, y: 30.209042695252734, icon: markIcon },
    { id: 6, x: 120.3350565266215, y: 30.173456231875097, icon: markIcon },
    { id: 7, x: 120.28144565378602, y: 30.223772936488828, icon: markIcon },
    { id: 8, x: 120.30674193694699, y: 30.191937841163863, icon: markIcon },
    { id: 9, x: 120.26003005042814, y: 30.167586339523147, icon: markIcon }
  ]
});

// tooltip模板
function markTipTemplate(markOption: any) {
  const name = 'monitor-map-tooltip';
  return `
    <div class="${name}">
      <div class="${name}__title">祝林红</div>
      <div class="${name}__content">
        <p>时间:2022-12-12  18:31:46</p>
        <p>位置:广德小区8号楼1单元1101</p>
        <p>报警内容:跌倒</p>
      </div>
    </div>
  `;
}
//#endregion
</script>
<style lang="scss">
.map {
    height: 493px;
    margin-bottom: 19px;
  }
</style>



版权声明:本文为weixin_45891332原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。