如何通过百度地图api绘制不规则多边形

129 阅读3分钟

本文主要介绍如何通过百度地图的JavaScript API v3.0版本绘制不规则多边形的相关内容

样例代码如下

html代码

<div ref={filingGridMap} id={'filingGridMap'} className={'map-box'} /> //地图载体
<div id={'myPanel'} /> // 地图搜索载体

ts部分代码

import React, { useEffect, useRef } from 'react';
import _ from 'lodash';


const scriptInterval = useRef(null);//js加载计时器
const filingGridMap = useRef(null);//地图div
const mapCanvas = useRef(null); // 地图主体渲染画布
const drawingManger = useRef(null); // 地图绘制标点功能
const drawOverlay = useRef(null); // 当前绘制的图形
const searchLocal = useRef(null); // 搜索
const allDrawPoint = useRef([]); // 所有点字符串

useEffect(() => {
    initMapScript().then(() => {
      setTimeout(() => {
        initMapCanvas();
      }, 1000);
    });
}, []);


    //初始化地图脚本
const initMapScript = () => {
    return new Promise((resolve, reject) => {
      if (window.BMap !== undefined && window.MapCore !== undefined && window.BMapLib !== undefined) {
        resolve('success');
      }
      let headElement = document.getElementsByTagName('head').item(0);
      let scriptElement = document.createElement('script');
      scriptElement.type = 'text/javascript';
      scriptElement.src = config.mapUrl; //百度地图引用地址
      scriptElement.onload = () => {
        scriptInterval.current = setInterval(() => {
          if (window.BMap !== undefined && window.MapCore !== undefined && window.BMapLib !== undefined) {
            clearInterval(scriptInterval.current);
            scriptInterval.current = null;
            resolve('success');
          }
        }, 100);
      };
      scriptElement.onerror = () => {
        if (scriptInterval.current) {
          clearInterval(scriptInterval.current);
          scriptInterval.current = null;
        }
        reject('error');
      };
      headElement.appendChild(scriptElement);
    });
};

    //初始化地图
const initMapCanvas = () => {
    mapCanvas.current = new window.BMap.Map(filingGridMap.current, { enableMapClick: false });
    const defaultPoint = new window.BMap.Point(98, 35); //默认设置一个中心点
    mapCanvas.current.centerAndZoom(defaultPoint, 6); //设置到中心点位置
    mapCanvas.current.enableScrollWheelZoom();//开启滚动缩放
    //这两个控件会被其他老版本地图页面干扰导致显示异常和位置异常
    mapCanvas.current.addControl(new window.BMap.ScaleControl({}));//比例尺
    mapCanvas.current.addControl(new window.BMap.NavigationControl({ anchor: window.BMAP_ANCHOR_TOP_RIGHT, offset: new window.BMap.Size(0, 20) } as any)); //缩放移动控件
    initMapDrawing(); //初始化地图绘制部分内容
    getGirdList(); //若需要默认绘制部分覆盖则可以在此处进行(这个方法在下面)
};

//调用接口进行默认绘制
const getGirdList =() =>{
    allDrawPoint.current = [];
    mapCanvas.current.clearOverlays();//删除所有覆盖物
    //接口查询默认绘制内容
    //drawGrid(item)//循环调用
    const viewBounds = new window.BMap.Bounds();
    allDrawPoint.current.forEach((item) => { //循环绘制会塞这个值
        viewBounds.extend(item);
    });
    mapCanvas.current.setViewport(viewBounds);
}

//获取绘制覆盖物的点坐标字符串
const getLocation = (path) => {
    let location = ""; // 坐标点用空格隔开
    if(path.length>0){
      path.forEach(function(item) {
        location = location + item.lng + " " + item.lat + ",";
      });
      location = location + path[0].lng + " " + path[0].lat;
    }
    return location
}

//通过坐标字符串获取bmap格式坐标列表以及中心点
const getPointAndCenter = (location) => {
    const list = location.split(',');
    const drawPointList = [];
    list.forEach((item) => {
      const pointList = item.split(' ');
      drawPointList.push(new window.BMap.Point(Number(pointList[0]), Number(pointList[1])));
    });
    //获取中心点
    const polygon = new window.BMap.Polygon(drawPointList);
    const bounds = polygon.getBounds();
    const centerPoint = bounds.getCenter(); //获取中心点
    return { drawPointList, centerPoint };
};

//设置网格区域点击监听
const listenerPolygon = (polygon) => {
    polygon.addEventListener('click', (event) => {
      //网格点击地图出现弹框
      if (drawOverlay.current) {//如果存在正在编辑的图形则关闭对应的编辑
        if (event.currentTarget.da === drawOverlay.current?.da) { //判断是否为同个绘制区域
          return;
        }
        drawOverlay.current.disableEditing();
      }
      const location = getLocation(polygon.getPath());
      const { drawPointList } = getPointAndCenter(location);
      const viewBounds = new window.BMap.Bounds();
      drawPointList.forEach((item) => {
        viewBounds.extend(item);
      });
      mapCanvas.current.setViewport(viewBounds);
      drawOverlay.current = polygon;
      console.log('图形编辑----', event);
      polygon.enableEditing(); //开启编辑
    });
};

//添加label
const addLabel = (centerPoint, name) => {
    const label = new window.BMap.Label(name, {
      position: centerPoint,
    });
    label.setStyle({
      color: '#fff', // 字体颜色
      fontSize: '12px', // 字体大小
      backgroundColor: '#ff8355', // 背景色
      padding: '5px',
      border: '1px solid #ff8355', // 边框大小
    });
    mapCanvas.current.addOverlay(label);
};

//初始化地图绘制
const initMapDrawing = () => {
    drawingManger.current = new window.BMapLib.DrawingManager(mapCanvas.current, {
            isOpen: false,
            enableDrawingTool: true, // 是否显示工具栏
            drawingMode: 'hander',
            drawingToolOptions: {
                anchor: window.BMAP_ANCHOR_TOP_RIGHT, // 工具栏停靠位置
                offset: new window.BMap.Size(80, 20),
                scale: 0.7, // 工具栏缩放比例
                drawingModes: ['polygon'], // 允许绘制的图形类型
            },
            polygonOptions: {
                path: [], // 设置多边形的路径
                strokeColor: '#4882f3', // 设置边框颜色
                strokeWeight: 2, // 设置边框宽度
                strokeOpacity: 0.8, // 设置边框透明度
                fillColor: '#4882f3', // 设置填充颜色
                fillOpacity: 0.2, // 设置填充透明度
                enableEditing: false, // 是否可编辑
            }
    });
    drawingManger.current.addEventListener('overlaycomplete', ({ overlay }) => {
        console.log('绘制完成----', overlay);
        if (drawOverlay.current) {//如果存在正在编辑的图形则关闭对应的编辑
        drawOverlay.current.disableEditing();
        }
        const location = getLocation(overlay.getPath());
        const { drawPointList } = getPointAndCenter(location);
        const viewBounds = new window.BMap.Bounds();
        drawPointList.forEach((item) => {
        viewBounds.extend(item);
        });
        mapCanvas.current.setViewport(viewBounds); //将绘制的多边形完全显示在屏幕正中间
        drawOverlay.current = overlay; //设置当前绘制的多边形
        overlay.enableEditing(); //开启编辑
        listenerPolygon(overlay);
    });
}

//非手动绘制多边形网格
const drawGrid = (data) => {
    if (!data.location || data.location === '0') {
      return;
    }
    const { drawPointList, centerPoint } = getPointAndCenter(data.location);
    allDrawPoint.current = allDrawPoint.current.concat(drawPointList);  //存储所有的点字符串,绘制全部后统一进行居中操作
    const polygon = new window.BMap.Polygon(drawPointList, {
      strokeColor: data?.border_color || '#4882f3', // 设置边框颜色
      strokeWeight: 2, // 设置边框宽度
      strokeOpacity: 0.8, // 设置边框透明度
      fillColor: data?.color_in_box || '#4882f3', // 设置填充颜色
      fillOpacity: 0.2, // 设置填充透明度
    });
    polygon.defaultData = { ...data }; //接口内容 直接获取里面获取
    addLabel(centerPoint, data.grid_name);
    mapCanvas.current.addOverlay(polygon);
    listenerPolygon(polygon);
};

//网格删除
const onGirdDelete = async () => {
    drawOverlay.current.disableEditing();
    mapCanvas.current.removeOverlay(drawOverlay.current);
    drawOverlay.current = null;
};

// 地图根据名称搜索
const onPointSearch = _.debounce((v) => {
    onClearSearch();
    if (v) {
      //根据输入项通过百度地图进行搜索具体坐标地址
      searchLocal.current = new window.BMap.LocalSearch(searchCity[searchCity.length - 1], {
        renderOptions: { map: mapCanvas.current, autoViewport: true, selectFirstResult: false, panel: 'myPanel' },
        pageCapacity: 5,
      });
      searchLocal.current.search(v);
    }
}, 500);

//清除搜索
const onClearSearch = () => {
    if (searchLocal.current) {
      searchLocal.current.clearResults();
      searchLocal.current = null;
    }
};