vue3+ts实现百度地图鼠标绘制多边形

发布于:2025-06-06 ⋅ 阅读:(23) ⋅ 点赞:(0)

百度地图api鼠标绘制地址: JavaScript API - 鼠标绘制 | 百度地图API SDK

 

index.vue文件引入组件

<map @submitMap="submitMap" />
import map from './components/map.vue';
//获取经纬度
const submitMap = (adress: any) => {
  const convertedData = convertCoordinates(adress);
  console.log(convertedData);
};
//使用 map 方法遍历数组,将每个对象转换为 [jd, wd] 形式的数组
function convertCoordinates(original: { jd: number; wd: number }[]): number[][] {
  return original.map((item) => [item.jd, item.wd]);
}

组件map.vue文件

<template>
  <div :class="isFull ? 'fullContain' : 'contain'">
    <div id="allmap" :class="isFull ? 'fullMap' : 'allmap'"></div>
    <div
      class="dialog-footer"
      v-if="showClearButton"
      :style="isFull ? 'height: 100%;width: 20%' : 'height: 500px'"
    >
      <div class="content">
        <div class="title">编辑网格</div>
        <div class="button-content">
          <el-button type="primary" @click="hzMap" v-if="showHzButton">绘制网格区域</el-button>
          <el-button type="primary" @click="editMap" v-if="!showHzButton">编辑网格区域</el-button>
          <el-button @click="clearnMap">清除网格区域</el-button>
        </div>
        <div class="title">使用说明</div>
        <div class="tishi">
          <p>1.选择颜色,在地图上拖动鼠标绘制网格范围,绘制完成后双击鼠标左键完成绘制。</p>
          <p>2.点击编辑按钮可对当前所绘网格区域进行修改。</p>
          <p>3.点击清空按钮可清空当前所绘制的网格区域。</p>
          <div class="button-content">
            <el-button type="primary" @click="mapSubimt">绘制完成</el-button>
          </div>
        </div>
      </div>
      <div :class="isFull ? 'sxFull' : 'allFull'" @click="fullClick">
        <el-icon color="#409efc">
          <FullScreen />
        </el-icon>
      </div>
    </div>
  </div>
</template>
<script lang="ts" name="Post" setup>
// 定义 dts 数组中对象的类型
interface DtsItem {
  jd: number; // 经度
  wd: number; // 纬度
}

// 修改 props 定义
const props = withDefaults(
  defineProps<{
    dts?: Array<DtsItem>; // 使用泛型 Array<DtsItem>
  }>(),
  {
    dts: () => [] // 默认值设为空数组
  }
);
const emit = defineEmits(['update:value']);
var map:any = null;
var polyline:any = null;
const mapPointList = ref([]);
var myGeo:any = null;
const showClearButton = ref(true);
const showHzButton = ref(true);
const isFull = ref(false);
watch(
  () => props.dts,
  () => {
    initEditMap();
  }
);
onMounted(() => {
  if (!map) {
    map = new window.BMapGL.Map('allmap');
    map.enableScrollWheelZoom(true);
    myGeo = new window.BMapGL.Geocoder();
    initMapWz();
  }
});

const initMapWz = () => {
  let region = '陕西省';
  // if (JSON.parse(window.localStorage.getItem('authorities')).level == 1) {
  //   region = JSON.parse(window.localStorage.getItem('authorities')).region01
  // } else if (JSON.parse(window.localStorage.getItem('authorities')).level == 2) {
  //   region =
  // 	JSON.parse(window.localStorage.getItem('authorities')).region01 +
  // 	JSON.parse(window.localStorage.getItem('authorities')).region02
  // } else if (JSON.parse(window.localStorage.getItem('authorities')).level == 3) {
  //   region =
  // 	JSON.parse(window.localStorage.getItem('authorities')).region01 +
  // 	JSON.parse(window.localStorage.getItem('authorities')).region02 +
  // 	JSON.parse(window.localStorage.getItem('authorities')).region03
  // } else if (JSON.parse(window.localStorage.getItem('authorities')).level == 4) {
  //   region =
  // 	JSON.parse(window.localStorage.getItem('authorities')).region01 +
  // 	JSON.parse(window.localStorage.getItem('authorities')).region02 +
  // 	JSON.parse(window.localStorage.getItem('authorities')).region03 +
  // 	JSON.parse(window.localStorage.getItem('authorities')).region04
  // } else if (JSON.parse(window.localStorage.getItem('authorities')).level == 5) {
  //   region =
  // 	JSON.parse(window.localStorage.getItem('authorities')).region01 +
  // 	JSON.parse(window.localStorage.getItem('authorities')).region02 +
  // 	JSON.parse(window.localStorage.getItem('authorities')).region03 +
  // 	JSON.parse(window.localStorage.getItem('authorities')).region04 +
  // 	JSON.parse(window.localStorage.getItem('authorities')).region05
  // }
  myGeo.getPoint(region, function (point:any) {
    if (point) {
      map.centerAndZoom(point, 16);
    } else {
      alert('您选择的地址没有解析到结果!');
    }
  });
};
const initEditMap = () => {
  if (map) {
    map.clearOverlays();
    if (props.dts.length > 0) {
      mapPointList.value = [];
      for (let item of props.dts) {
        const point = new window.BMapGL.Point(item.jd, item.wd);
        mapPointList.value.push(point);
      }
      showHzButton.value = false;
      polyline = new window.BMapGL.Polygon(mapPointList.value, {
        strokeColor: '#39c19e',
        strokeWeight: 2,
        strokeOpacity: 1,
        fillColor: '#39c19e'
      });
      map.addOverlay(polyline);
    }
  }
};
const uploadDTDW = (regionName:any) => {
  if (myGeo) {
    myGeo.getPoint(regionName, function (point:any) {
      if (point) {
        map.centerAndZoom(point, 16);
      } else {
        alert('您选择的地址没有解析到结果!');
      }
    });
  }
};
const editMap = () => {
  if (polyline.enableEditing) {
    if (mapPointList.value.length >= 2) {
      polyline.enableEditing();
    }
  }
};
const hzMap = () => {
  if (polyline) {
    polyline.disableEditing();
  }
  showHzButton.value = false;
  mzwg();
};
const mzwg = () => {
  map.addEventListener('click', function (e:any) {
    var point = new window.BMapGL.Point(e.latlng.lng, e.latlng.lat);
    mapPointList.value.push(point);
    if (mapPointList.value.length >= 2) {
      if (polyline != null) {
        polyline.setPath(mapPointList.value);
      } else {
        polyline = new window.BMapGL.Polygon(mapPointList.value, {
          strokeColor: '#39c19e',
          strokeWeight: 2,
          strokeOpacity: 1,
          fillColor: '#39c19e'
        });
      }
      map.addOverlay(polyline);
    }
  });
  map.addEventListener('dblclick', function (e:any) {
    map.removeEventListener('click');
    map.removeEventListener('mousemove');
    map.removeEventListener('dblclick');
  });
  map.addEventListener('mousemove', function (e:any) {
    if (mapPointList.value.length > 0) {
      if (polyline == null) {
        polyline = new window.BMapGL.Polygon(
          [...mapPointList.value, new window.BMapGL.Point(e.latlng.lng, e.latlng.lat)],
          {
            strokeColor: '#39c19e',
            strokeWeight: 2,
            strokeOpacity: 1,
            fillColor: '#39c19e'
          }
        );
        map.addOverlay(polyline);
      } else {
        polyline.setPath([
          ...mapPointList.value,
          new window.BMapGL.Point(e.latlng.lng, e.latlng.lat)
        ]);
        map.addOverlay(polyline);
      }
    }
  });
};
const removeOverlay = () => {
  if (polyline) {
    polyline.disableEditing();
    polyline = null;
  }
  showHzButton.value = true;
  map.clearOverlays();
  mapPointList.value = [];
};
const mapSubimt = () => {
  let point: { jd: number; wd: number }[] = []; // 初始化为空数组
  if (polyline) {
    point = getPoint();
  }
  if (isFull.value) {
    isFull.value = false;
  }
  emit('submitMap', point);
};

const getPoint = (): { jd: number; wd: number }[] => {
  const point: { jd: number; wd: number }[] = [];
  const path = polyline.getPath();
  for (let index = 0; index < path.length; index++) {
    const currentPoint = path[index];
    const map = {
      jd: currentPoint.lng,
      wd: currentPoint.lat
    };
    // 使用 some 避免重复项
    if (!point.some(p => p.jd === map.jd && p.wd === map.wd)) {
      point.push(map);
    }
  }
  return point;
};
const clearnMap = () => {
  polyline = null;
  showHzButton.value = true;
  map.clearOverlays();
  mapPointList.value = [];
  // showHzButton.value = true
  // map.clearOverlays()
  // mapPointList = []
};
const init = (e:any) => {
  showClearButton.value = e;
};

//绘制当前区域下所有的网格区域
const hadDrawWGXX = (e:any) => {
  e.forEach((contentItem:any) => {
    var points: any[] = [];
    
    var opts;
    contentItem.dts.forEach((item: { jd: any; wd: any; }, index: number) => {
      points.push(new BMapGL.Point(item.jd, item.wd));
      if (index == 0) {
        opts = {
          position: new BMapGL.Point(item.jd, item.wd), // 指定文本标注所在的地理位置
          offset: new BMapGL.Size(10, -40) // 设置文本偏移量
        };
        const label = new BMapGL.Label(contentItem.wgName, opts);
        label.setStyle({
          color: 'blue',
          borderRadius: '5px',
          borderColor: '#ccc',
          padding: '10px',
          fontSize: '16px',
          height: '40px',
          lineHeight: '20px'
        });
        map.addOverlay(label);
        label.disableMassClear();
      }
    });
    const polylineddd = new window.BMapGL.Polygon(points, {
      strokeColor: '#EBAF00',
      strokeWeight: 1,
      strokeOpacity: 1,
      fillColor: '#EBAF00',
      fillOpacity: 0.2
    });
    map.addOverlay(polylineddd);
    polylineddd.disableMassClear();
  });
};
const fullClick = () => {
  isFull.value = !isFull.value;
};

const disgrogMap = () => {
  map.getOverlays().map((item: any) => {
    map.removeOverlay(item);
  });
};
</script>

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

.fullContain {
  position: fixed;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  background-color: white;
  z-index: 99999;
}

.allmap {
  width: 75%;
  height: 455px;
  float: left;
}

.fullMap {
  width: 80%;
  height: 100%;
  float: left;
}

.dialog-footer {
  float: right;
  width: 25%;
  height: 455px !important;
  border: 1px solid #e5e5e5;
  border-radius: 2px;

  .content {
    clear: both;
    margin-left: 20px;
    margin-right: 20px;

    .title {
      font-size: 20px;
      font-family: SourceHanSansCN-Medium, SourceHanSansCN;
      font-weight: 500;
      color: #333;
      height: 20px;
      line-height: 20px;
      border-left: 3px solid #188dff;
      padding-left: 10px;
      margin-bottom: 20px;
      margin-top: 20px;
      margin-bottom: 20px;
    }

    .tishi {
      font-size: 14px;
      height: 14px;
      line-height: 18px;

      .button-content {
        margin-top: 20px;
      }
    }

    .button-content {
      width: 100%;

      :deep(.el-button) {
        margin: 0px !important;
        width: 100%;
        margin-bottom: 10px !important;
      }
    }

    .hzwc {
      margin-top: 20px;
    }
  }
}

.allFull {
  position: absolute;
  left: 70%;
  top: 15px;
  color: #39c19e;
  z-index: 100;
  font-size: 25px;
}

.sxFull {
  position: absolute;
  left: 75%;
  top: 30px;
  color: #39c19e;
  z-index: 100;
  font-size: 25px;
}
</style>


网站公告

今日签到

点亮在社区的每一天
去签到