屏幕截图 2022-12-04 215851
鼠标工具-绘制覆盖物

官方示例连接
这个示例中只给出了绘制图形,并未给出获取图形坐标点与根据坐标点将图形显示到地图上(在官方给出的文档找中可以找到具体的实现方法,这里给做一个汇总方便使用)

1、获取绘制图形的坐标点

根据给出的示例共有5中图形,分别是 点、折线、多边形、矩形、圆,其中点的获取方法是一种,折线、多边形的获取是一种,矩形与圆各自是一个获取方法。
根据示例中可以知道监听draw事件可获取画好的覆盖物

    var mouseTool = new AMap.MouseTool(map); 
    //监听draw事件可获取画好的覆盖物
    var overlays = [];
    mouseTool.on('draw',function(e){
        overlays.push(e.obj);
    }) 

就在这个方法中获取画好的覆盖物坐标点,根据官网的文档查到不同覆盖物的获取方法
点为getPosition();
折线、多边形为getPath();
矩形也是getPath()但获取到坐标点数据结构与折线和多边形不一致不能用同一个方法解析(下文可以看出);
圆的方法比较特殊分圆点getCenter()与圆形的半径getRadius()

    mouseTool.on('draw',function(e){
    //choiceType为选择的遮盖物类型
        switch(choiceType){
            case 'marker':{
                const sj= e.obj.getPosition();
                 .........//解析获得的数据才能得到示例
                  //示例: [114.184851,30.490025]
                break;
            }
            case 'polyline':
            case 'polygon':{
                var dbx= e.obj.getPath()
                .........//解析获得的数据才能得到示例
                //示例:  [114.296832,30.579832;114.296634,30.579518;114.297353,30.579444;114.297755,30.57985;114.297165,30.579915]
                break;
            }
            case 'rectangle':{
                const dbx= e.obj.getPath()
                //西南 东北
                const northeast= dbx[0];
                const southwest= dbx[2];
                 .........//解析获得的数据才能得到示例
                 //示例: [[116.356449, 39.859008],[116.417901, 39.893797]]
                break;
            }
            case 'circle':{
                const Center=e.obj.getCenter();//获取圆中心点
                const Radius=e.obj.getRadius();//获取圆形的半径
                 .........//解析获得的数据才能得到示例
                break;
            }
        }

获取到坐标点后可以保存到文件或者已字符串的形式保存到数据库中,看具体的业务需求。

2、根据坐标点显示覆盖物

将坐标点从文件或者数据库中拿出来后是一个字符串形式的,但是遮盖物的显示需要的坐标点是数组结构,即便字符串中的坐标点带有[]还是无法解析,需要手动的给转成数组数组因此在获取坐标点进行保存时就可以选择不给拼接上[]方便现在字符串转数组。

//将遮盖物的数据显示到地图上
//type 为要显示遮盖物的类型
    function see(type){
      switch(type){
        case 'marker':{
           //需要的格式 数组[116.356449, 39.859008]
            const marker = new AMap.Marker({
                position: path,
            });
            map.add(marker)
            map.setFitView([ marker ])
            break;
        }
        case 'polyline':{
            const polyline = new AMap.Polyline({
                path: path,
                isOutline: true,
                outlineColor: '#ffeeff',
                borderWeight: 3,// 线条宽度,默认为 1
                strokeColor: "#3366FF", // 线条颜色
                strokeOpacity: 1,
                strokeWeight: 6,
                // 折线样式还支持 'dashed'
                strokeStyle: "solid",
                // strokeStyle是dashed时有效
                strokeDasharray: [10, 5],
                lineJoin: 'round',// 折线拐点连接处样式
                lineCap: 'round',
                zIndex: 50,
            })
            map.add(polyline)
            // 缩放地图到合适的视野级别
            map.setFitView([ polyline ])
            break;
        }
        case 'polygon':{
          //需要的格式 数组 [[116.356449, 39.859008], [116.417901, 39.893797]]
           // 数据结构为 数组 套 数组 [[1,1],[2,2]]
            const polygon =  new AMap.Polygon({
                path: path,
                strokeColor: "#FF33FF", 
                strokeWeight: 6,
                strokeOpacity: 0.2,
                fillOpacity: 0.4,
                fillColor: '#1791fc',
                zIndex: 50,
            })
            map.add(polygon)
            // 缩放地图到合适的视野级别
            map.setFitView([ polygon ])
            break;
        }
        case 'rectangle':{
          //需要的格式 数组 [116.356449, 39.859008], [116.417901, 39.893797]
            const rectangle = new AMap.Rectangle({
                bounds:new AMap.Bounds(path),
                strokeColor:'red',
                strokeWeight: 6,
                strokeOpacity:0.5,
                strokeDasharray: [30,10],
                // strokeStyle还支持 solid
                strokeStyle: 'dashed',
                fillColor:'blue',
                fillOpacity:0.5,
                cursor:'pointer',
                zIndex:50,
            })
            rectangle.setMap(map)
            // 缩放地图到合适的视野级别
            map.setFitView([ rectangle ])
            break;
        }
        case 'circle':{
            //path 将圆的半径与圆心坐标点拼装起来 
            const circle = new AMap.Circle({
                center: path[1],
                radius: path[0], //半径
                borderWeight: 3,
                strokeColor: "#FF33FF", 
                strokeOpacity: 1,
                strokeWeight: 6,
                strokeOpacity: 0.2,
                fillOpacity: 0.4,
                strokeStyle: 'dashed',
                strokeDasharray: [10, 10], 
                // 线样式还支持 'dashed'
                fillColor: '#1791fc',
                zIndex: 50,
            })
            circle.setMap(map)
            // 缩放地图到合适的视野级别
            map.setFitView([ circle ])
            break;
        }
      }
    }

其他的就是是否允许画和显示多个遮盖物,这个根据具体自己的业务场景具体分析。

3、以下是完整的代码,根据注释可以将其改成公共页面根据参数来操作覆盖物。

<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="chrome=1">
    <meta name="viewport" content="initial-scale=1.0, user-scalable=no, width=device-width">
    <link rel="stylesheet" href="https://a.amap.com/jsapi_demos/static/demo-center/css/demo-center.css" type="text/css">
    <style>
      html,body,#container{
        height: 100%
      }
      .input-item{
        height: 2.2rem;
      }
      .btn{
        margin: 0 1rem 0 0.005rem;
      } 
      .switch {
      padding: 3.75rem 1.25rem;
      margin-bottom: 1rem;
      border-radius: .25rem;
      position: fixed;
      top: 1rem;
      width: auto;
      border-width: 0;
      right: 1rem;
      }
      .input-text{
        width: 4rem;
        margin-right:1rem;
      }
    </style>
    <title>覆盖物绘制</title>
  </head>
  <body>
    <div id='container'></div>
    <div class='info'>操作说明:圆和矩形通过拖拽来绘制,其他覆盖物通过点击来绘制</div>
    <div class="switch">'+
      <input id="toggle" type="button" class="btn" value="平面/卫星切换" />
      </div>
    <div class="input-card" style='width: 27rem;'>
        <div class="input-item" id="chart1">
          <input type="radio" name='func' value='marker'><span class="input-text">画点</span>
          <input type="radio" name='func' value='polyline'><span class="input-text">画折线</span>
          <input type="radio" name='func' value='polygon'><span class="input-text" style='width:5rem;'>画多边形</span>
        </div>
        <div class="input-item" id="chart2">
          <input type="radio" name='func' value='rectangle'><span class="input-text">画矩形</span>
          <input type="radio" name='func' value='circle'><span class="input-text">画圆</span>
        </div>
        <div class="input-item">
            <input id="confirm" type="button" class="btn" value="确认" />
            <input id="clear" type="button" class="btn" value="清除" />
            <input id="removeAllOverlay" type="button" class="btn" value="清除所有覆盖物" />
            <input id="close" type="button" class="btn" value="关闭绘图" />
        </div>
    </div>
    <script src="https://webapi.amap.com/maps?v=1.4.15&key=你的key&plugin=AMap.MouseTool"></script>
    <script type="text/javascript">

    //定义全局数据,可以由数据库查询也可以其他页面传值
    var path=[114.304588,30.593449];//覆盖物数据 数组格式  页面传值过来时要注意 字符串类型需转换 不处理的话会报错
    /**覆盖物类型 
     * marker 画点
     * polyline 画折线
     * polygon 画多边形
     * rectangle 画矩形
     * circle 画圆
    */
    var choiceType ='marker';
    var choiceData;//画覆盖物后得到的数据
    var operationType="free";//操作类型: decide 由传值决定覆盖物类型;  free  用户自己选择覆盖物类型 默认

    //接受其他页面传来的值,因为我这个语言页面传值后会变成字符串所以需要处理一下变成数组的格式,
    //如果传值过来的 path 是数组格式 并且符合 see 中的示例格式就可以不用处理 否则就将下列3个参数的接受方法换成你所使用的语言 并进行处理
    // marker 画点 polygon 画多边形 的格式以测试过没有问题,其余的需要自行尝试

    // choiceType = F.queryString('choiceType');
    //  operationType = F.queryString('operationType');
    //  const originalPath = F.queryString("path");
    //  if(originalPath!=null||originalPath!=""||originalPath!=undefined){
    //     switch(choiceType){
    //         case 'marker':{
    //             path=originalPath.split(",");
    //             break;
    //         }
    //         case 'polyline':{
    //             break;
    //         }
    //         case 'polygon':{
    //             var qy=[];
    //             const original=originalPath.split(";");
    //             original.forEach(i => {
    //                 const zb=i.split(",");
    //                 qy.push(zb);
    //             });
    //             path=qy;
    //             break;
    //         }
    //         case 'rectangle':{
    //             var qy=[];
    //             const original=originalPath.split(";");
    //             original.forEach(i => {
    //                 const zb=i.split(",");
    //                 qy.push(zb);
    //             });
    //             path=qy;
    //             break;
    //         }
    //         case 'circle':{
    //             break;
    //         }
    //       }
    //  }


    //定义地图初始化
    var map = new AMap.Map('container',{
        zoom:14
    });

    var mouseTool = new AMap.MouseTool(map); 
    //页面初始化加载 需要显示的覆盖物 与 需要画覆盖物类型
    if(operationType=="decide"){
        document.getElementById('chart1').remove();
        document.getElementById('chart2').remove();
    }
    if(path!=null&&path!=""&&path!=undefined&& path[0].length>0&& path[0]!="undefined"){  
        see(choiceType);
    }
    draw(choiceType);

    //监听draw事件可获取画好的覆盖物
    var overlays = [];
    mouseTool.on('draw',function(e){
        overlays.push(e.obj);
        var data="";//组装数据的方法需要根据项目调试,有时候不用在处理数据时前后加[] 
        switch(choiceType){
            case 'marker':{
                const sj= e.obj.getPosition();
                data=sj.lng+","+sj.lat;   //示例: 114.184851,30.490025
                break;
            }
            case 'polyline':
            case 'polygon':{
                var dbx= e.obj.getPath()
                for (let i = 0; i < dbx.length; i++) {
                    const sj = dbx[i];
                    if(i==0){
                        data=sj.lng+","+sj.lat
                    }else{
                        data+=";"+ sj.lng+","+sj.lat
                    }
                }
                //示例:  114.296832,30.579832;114.296634,30.579518;114.297353,30.579444;114.297755,30.57985;114.297165,30.579915
                break;
            }
            case 'rectangle':{
                const dbx= e.obj.getPath()
                console.log("log"+dbx);
                //西南 东北
                const northeast= dbx[0];
                const southwest= dbx[2];
                data=northeast.lng+","+northeast.lat+";"+southwest.lng+","+southwest.lat
                //示例: 116.356449, 39.859008;116.417901, 39.893797
                break;
            }
            case 'circle':{
                const Center=e.obj.getCenter();//获取圆中心点
                const Radius=e.obj.getRadius();//获取圆形的半径
                data=Radius+";["+Center+"]";
                break;
            }
        }
        choiceData=data;
        // console.log("监听draw事件可获取画好的覆盖物:"+data);
    }) 
    
    //初始化画覆盖物方法
    function draw(type){
	    choiceType=type;
      switch(type){
        case 'marker':{
            mouseTool.marker({
              //同Marker的Option设置
            });
            break;
        }
        case 'polyline':{
            mouseTool.polyline({
              strokeColor:'#80d8ff'
              //同Polyline的Option设置
            });
            break;
        }
        case 'polygon':{
            mouseTool.polygon({
              fillColor:'#00b0ff',
              strokeColor:'#80d8ff'
              //同Polygon的Option设置
            });
            break;
        }
        case 'rectangle':{
            mouseTool.rectangle({
              fillColor:'#00b0ff',
              strokeColor:'#80d8ff'
              //同Polygon的Option设置
            });
            break;
        }
        case 'circle':{
            mouseTool.circle({
              fillColor:'#00b0ff',
              strokeColor:'#80d8ff'
              //同Circle的Option设置
            });
            break;
        }
      }
    }
    var radios = document.getElementsByName('func');
    for(var i=0;i<radios.length;i+=1){
        radios[i].onchange = function(e){
          draw(e.target.value)
        }
    }

    //清除画的覆盖物
    document.getElementById('clear').onclick = function(){
        map.remove(overlays)
        overlays = [];
        choiceData=undefined;
    }  
    document.getElementById('close').onclick = function(){
        mouseTool.close(true)//关闭,并清除覆盖物
        for(var i=0;i<radios.length;i+=1){
            radios[i].checked = false;
        }
    }

    // 绑定移除事件
    document.getElementById("removeAllOverlay").onclick = removeAllOverlay;
    function removeAllOverlay(){
        // 清除地图上所有添加的覆盖物
        map.clearMap();
        choiceData=undefined;
    }

    //将遮盖物的数据显示到地图上
    function see(type){
      switch(type){
        case 'marker':{
           //需要的格式 数组[116.356449, 39.859008]
            const marker = new AMap.Marker({
                position: path,
                // offset: new AMap.Pixel(-17, -42) // 相对于基点的偏移位置
            });
            map.add(marker)
            map.setFitView([ marker ])
            break;
        }
        case 'polyline':{
            const polyline = new AMap.Polyline({
                path: path,
                isOutline: true,
                outlineColor: '#ffeeff',
                borderWeight: 3,// 线条宽度,默认为 1
                strokeColor: "#3366FF", // 线条颜色
                strokeOpacity: 1,
                strokeWeight: 6,
                // 折线样式还支持 'dashed'
                strokeStyle: "solid",
                // strokeStyle是dashed时有效
                strokeDasharray: [10, 5],
                lineJoin: 'round',// 折线拐点连接处样式
                lineCap: 'round',
                zIndex: 50,
            })
            map.add(polyline)
            // 缩放地图到合适的视野级别
            map.setFitView([ polyline ])
            break;
        }
        case 'polygon':{
          //需要的格式 数组 [[116.356449, 39.859008], [116.417901, 39.893797]]
           // 数据结构为 数组 套 数组 [[1,1],[2,2]]
            const polygon =  new AMap.Polygon({
                path: path,
                strokeColor: "#FF33FF", 
                strokeWeight: 6,
                strokeOpacity: 0.2,
                fillOpacity: 0.4,
                fillColor: '#1791fc',
                zIndex: 50,
            })
            
            map.add(polygon)
            // 缩放地图到合适的视野级别
            map.setFitView([ polygon ])
            break;
        }
        case 'rectangle':{
          //需要的格式 数组 [116.356449, 39.859008], [116.417901, 39.893797]
            const rectangle = new AMap.Rectangle({
                bounds:new AMap.Bounds(path),
                strokeColor:'red',
                strokeWeight: 6,
                strokeOpacity:0.5,
                strokeDasharray: [30,10],
                // strokeStyle还支持 solid
                strokeStyle: 'dashed',
                fillColor:'blue',
                fillOpacity:0.5,
                cursor:'pointer',
                zIndex:50,
            })
        
            rectangle.setMap(map)
            // 缩放地图到合适的视野级别
            map.setFitView([ rectangle ])
        
            break;
        }
        case 'circle':{
            const sj= path.split(";");
            const circle = new AMap.Circle({
                center: sj[1],
                radius: sj[0], //半径
                borderWeight: 3,
                strokeColor: "#FF33FF", 
                strokeOpacity: 1,
                strokeWeight: 6,
                strokeOpacity: 0.2,
                fillOpacity: 0.4,
                strokeStyle: 'dashed',
                strokeDasharray: [10, 10], 
                // 线样式还支持 'dashed'
                fillColor: '#1791fc',
                zIndex: 50,
            })
            circle.setMap(map)
            // 缩放地图到合适的视野级别
            map.setFitView([ circle ])
            break;
        }
      }
    }

    //确认 得到遮盖物数据
    document.getElementById('confirm').onclick = function(){
        if(choiceData!=null||choiceData!=""||choiceData!=undefined){
            //校验是否允许存在多个点 
            //如果允许要考虑获取多个遮盖物数据
            //不允许要考虑禁止用户标记多个遮盖物
        }
       console.log("confirm"+choiceData);
    }  

    //平面地图与卫星地图切换
    var TileLayer= new AMap.TileLayer.Satellite()
    TileLayer.setMap(map);
    var isVisible = true;
    document.getElementById('toggle').onclick = function(){
        if (isVisible) {
            TileLayer.hide();
            isVisible = false;
        } else {
            TileLayer.show();
            isVisible = true;
        }
    }  
    </script>
  </body>
</html>