• 根据指定手绘图纸照片行政区划自定义绘制对应区域边界生成geoJOSN的解决方案


    项目需求

    指定某区域(非省市区县乡镇标准行政区划),做功能边界分区,实现Echarts地理坐标数据可视化展示。

    提供信息在这里插入图片描述

    项目分析

    • 要在Echarts上实现地理坐标可视化,必须使用geoJSON格式文件;
    • 项目只能提供手绘图纸,需要将手绘图纸转换为可以识别的经纬度坐标信息;
    • 如何将图纸绑定在百度地图上,使图纸和百度地图区域相重合,按照提供的区域边界,拾取对应的经纬度坐标;
    • 将拾取的经纬度坐标做换为geoJSON;
    • 引入Echarts,进行开发;

    操作步骤

    为简化流程和项目信息外漏,以随意某地作为案例实施步骤演示。

    固定地图

    在百度地图上找到对应的区域,并设置对应的地图显示级别,map.centerAndZoom(new BMap.Point(112.761393, 28.101516), 18)方便后面图片和区域相重合;截图固定地图级别的图片:map1.jpg

    在这里插入图片描述

    图片处理

    在PSD中打开map1.jpg文件,将功能区划在PSD中进行处理,扣除多余的部分,只要行政划分的区域,且图片的大小依据步骤1中截图的大小,一一对应。
    在这里插入图片描述
    3.隐藏地图,只留行政区划部分区域,保存新的文件为:newmap.png
    在这里插入图片描述

    代码开发

    使用的技能:

    1. 百度地图API的引入;
    2. 百度地图绘制多边形并获取所有点的坐标;
    3. HTML&CSS相对定位和绝对定位,实现图片和地图的重合;
    4. 将拾取的坐标转化为标准的geoJOSN;

    引入百度地图api

        <script type="text/javascript"
                src="http://api.map.baidu.com/api?v=3.0&ak=你的AK"></script>
    

    创建容器

    <div id="main">
        <div id="img"><img src="images/lll.png" alt=""></div>
        <div id="container"></div>
    </div>
    <div id="text"><input id="startBtn" type="button" onclick="startTool();" value="开启取点"/>
        <input type="button" onclick="map.clearOverlays();document.getElementById('info').innerHTML = '';points=[];"
               value="清除"/>
    </div>
    
    <div id="info">坐标:</div>
    

    CSS样式表

      body, html {
       
       
       
                width: 100%;
                height: 100%;
                margin: 0;
                font-family: "微软雅黑";
            }
    
            #main {
       
       
       
                position: relative;
            }
    
            #img {
       
       
       
                position: absolute;
                opacity: 0.5;
                left: 500px;
                top: 200px;
                z-index: -999;
            }
    
            #container {
       
       
       
                width: 100%;
                height: 80vh;
                border: 1px solid gray;
                position: absolute;
                opacity: 0.7;
                z-index: 9999;
            }
    
            #text {
       
       
       
                position: absolute;
                z-index: 9999;
                left: 50px;
                bottom: 120px;
            }
    
            #info {
       
       
       
                position: absolute;
                z-index: 999999;
                left: 50px;
                bottom: 80px;
            }
    

    实现的布局如图:
    在这里插入图片描述

    1. 图片置于最底层,方便按照边界拾取经纬度;
    2. 地图设置一定的透明度,方便开发图片;
    3. 移动地图和图片相重合,绘制多边形并获取所有点的坐标;

    绘制多边形并获取所有点的坐标

    var map = new BMap.Map("container", {
       
       
       enableMapClick: false});
        map.centerAndZoom(new BMap.Point(112.761393, 28.101516), 18);
        map.enableScrollWheelZoom();
    
        /*设置版权控件位置 -Begin*/
        var cr = new BMap.CopyrightControl({
       
       
       anchor: BMAP_ANCHOR_TOP_RIGHT});
        map.addControl(cr); //添加版权控件
        var bs = map.getBounds();   //返回地图可视区域
        cr.addCopyright({
       
       
       
            id: 1,
            content: "<div style='font-size:12px;margin: 10px;padding:5px;background: rgba(255,255,255,.8);'>Copyright �0�8 漏刻有时百度地图API开发</div>",
            bounds: bs
        });
        /*设置版权控件位置 -End*/
    
        var key = 1;    //开关
        var newpoint;   //一个经纬度
        var points = [];    //数组,放经纬度信息
        var polyline = new BMap.Polyline(); //折线覆盖物
    
        function startTool() {
       
       
          //开关函数
            if (key == 1) {
       
       
       
                document.getElementById("startBtn").style.background = "green";
                document.getElementById("startBtn").style.color = "white";
                document.getElementById("startBtn").value = "开启状态";
                key = 0;
            }
            else {
       
       
       
                document.getElementById("startBtn").style.background = "red";
                document.getElementById("startBtn").value = "关闭状态";
                key = 1;
            }
        }
    
        //单击地图,形成折线覆盖物
        map.addEventListener("click", function (e) {
       
       
       
            newpoint = new BMap.Point(e.point.lng, e.point.lat);
            if (key == 0) {
       
       
       
                //    if(points[points.length].lng==points[points.length-1].lng){alert(111);}
                points.push(newpoint);  //将新增的点放到数组中
                polyline.setPath(points);   //设置折线的点数组
                map.addOverlay(polyline);   //将折线添加到地图上
                /*02.数据集格式*/
                document.getElementById("info").innerHTML += "[" + e.point.lng + "," + e.point.lat + "],";
    
            }
        });
    
        //双击地图,形成多边形覆盖物
        map.addEventListener("dblclick", function (e) {
       
       
       
            if (key == 0) {
       
       
       
                map.disableDoubleClickZoom();   //关闭双击放大
                var polygon = new BMap.Polygon(points);
                map.addOverlay(polygon);   //将折线添加到地图上
            }
        });
    

    在这里插入图片描述

    [112.7584914732037,28.10156777873837],[112.759075371785,28.1008667598055],[112.76014435534152,28.10005420934206],[112.76070130475752,28.10014183763234],[112.76055757587598,28.10128099882524],[112.76028808422306,28.101519982139973],[112.7585094393139,28.101599643125347]
    

    生成geoJSON

    {
       
       
       
      "type": "FeatureCollection",
      "features": [
        {
       
       
       
          "type": "Feature",
          "properties": {
       
       
       },
          "geometry": {
       
       
       
            "type": "LineString",
            "coordinates": [
              [
                112.7584914732037,
                28.10156777873837
              ],
              [
                112.759075371785,
                28.1008667598055
              ],
              [
                112.76014435534152,
                28.10005420934206
              ],
              [
                112.76070130475752,
                28.10014183763234
              ],
              [
                112.76055757587598,
                28.10128099882524
              ],
              [
                112.76028808422306,
                28.101519982139973
              ],
              [
                112.7585094393139,
                28.101599643125347
              ]
            ]
          }
        }
      ]
    }
    

    后续总结

    1. 第一种尝试,是使用百度标注,将图片作为一个maker使用,好在maker可以自由移动,方便对齐区域;而实际上,将图片引入百度地图API后,是无法缩放的,实现不了图片和地图的重合;
    2. 第二种尝试,使用GroundOverlay,地面图层的叠加,难点在于无法确定可视范围的西南角SW和东北角NE,就无法精准位置;同时该功能无法调整图片大小,无法移动和缩放图片,也实现不了图片和地图的重合;
    3. 返璞归真,利用CSS层叠的概念,实现图片和地图自由移动的特性,实现图片和地图的重合。
    4. 完成项目,希望有时间将该功能整理成一个插件,以便解决乡镇边界,村级边界、经济开发区边界等等自定义项目的开发。

    LOCKDATAV DONE!

  • 相关阅读:
    测试PHP-FPM的工作流中的疑惑点
    摘要
    Centrifugo简单试用
    react-redux的基本用法
    PHP中使用ElasticSearch(二)
    PHP中使用ElasticSearch(一)
    Vue中的状态管理器
    Laravel数据库迁移
    快速搭建一个vue开发环境
    使用cURL尝试ElasticSearch
  • 原文地址:https://www.cnblogs.com/fireicesion/p/14691458.html
Copyright © 2020-2023  润新知