• iClient for Leaflet实现动态绘圆的几何查询


    作者:ls

    【目录】

    • 背景
    • 前期准备
    • 呈现效果
    • 实现过程
    • 完整代码

    【背景】

    几何查询是WebGIS项目中一项比较常用的功能,SuperMap iClient 产品支持的几何对象类型众多,能够满足用户的许多需求。

    图1 可用于查询的几何对象近期遇到许多小伙伴反应,绘制圆形进行几何查询却得不到预期结果。这是因为 GeoJSON 规范中不支持圆,在主流框架下绘制的圆形并非面对象(Polygon),而是由圆心和半径定义得到的一个圆对象。为了实现圆形查询,就需要将圆对象转化为面对象,接下来让我们看一下实现效果和具体过程:
    (1)添加绘制控件;
    (2)获取绘制结果并利用插件生成面对象;
    (3)将面对象传入几何对象查询,在地图上呈现结果。

    【前期准备】

    ①地图服务:https://iserver.supermap.io/iserver/services/map-world/rest/maps/World
    ②所需插件:leaflet.draw、leaflet-geoman

    【呈现效果】

    在这里插入图片描述

    【实现过程】

    (1)引入必要文件

    <script type="text/javascript" include="leaflet.draw" src="../../dist/leaflet/include-leaflet.js"></script>
    <script src="https://unpkg.com/@geoman-io/leaflet-geoman-free@latest/dist/leaflet-geoman.min.js"></script>
    <link rel="stylesheet" href="https://unpkg.com/@geoman-io/leaflet-geoman-free@latest/dist/leaflet-geoman.css" />
    
    • 1
    • 2
    • 3

    (2)加载地图服务

    var map, url = "https://iserver.supermap.io/iserver/services/map-world/rest/maps/World";
    map = L.map('map', {
      crs: L.CRS.EPSG4326,
      center: [0, 0],
      maxZoom: 18,
      zoom: 1
    });
    new L.supermap.TiledMapLayer(url).addTo(map);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    (3)定义查询功能

    function query(lat,lng,r) {
      // 利用传入的经纬度和半径值构造一个L.circle对象
            var circle = L.circle([lat,lng], {color: 'red',radius:r});
      // 借助circleToPolygon()方法,将L.circle转换为L.polygon,其中第二个参数为polygon边的数量
            var polygon = L.PM.Utils.circleToPolygon(circle, 600);
            var param = new L.supermap.QueryByGeometryParameters({
                queryParams: {name: "Capitals@World.1"},
                geometry: polygon
            });
            new L.supermap
                .QueryService(url)
                .queryByGeometry(param, function (serviceResult) {
                    var result = serviceResult.result;
                    var count = result.totalCount;
                    resultLayer = L.geoJSON(result.recordsets[0].features).addTo(map);
                    var popup = L.popup().setLatLng([lat,lng]).setContent('半径约为:'+ (r/1000).toFixed(2) +'千米
    结果数量:'
    +count+'个').openOn(map); }); }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    (4)加载绘制工具,仅开启圆形绘制功能

    var editableLayers = new L.FeatureGroup();
        map.addLayer(editableLayers);
        var options = {
            position: 'topleft',
            draw: {
                polyline: false,
                polygon: false,
                circle: {},
                rectangle: false,
                marker: false,
                remove: false
            },
            edit: {
                featureGroup: editableLayers,
                remove: false
            }
        };
        var drawControl = new L.Control.Draw(options);
        map.addControl(drawControl);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    (5)添加绘制触发事件方法

    handleMapEvent(drawControl._container, map);
        map.on(L.Draw.Event.CREATED, function (e) {
            var type = e.layerType,
                layer = e.layer;
            if (type === 'marker') {
                layer.bindPopup('A popup!');
            }
            editableLayers.addLayer(layer);
          // 获取绘制圆形的半径、圆心经纬度,并传入query()方法
            var r = layer._mRadius;
            var lat = layer._latlng.lat;
            var lng = layer._latlng.lng;
            query(lat,lng,r);
        });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    【完整代码】

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    <title data-i18n="resources.title_tiledMapLayer4326"></title>
    <script type="text/javascript" src="../js/include-web.js"></script>
    </head>
    <body style=" margin: 0;overflow: hidden;background: #fff;width: 100%;height:100%;position: absolute;top: 0;">
    <div id="map" style="margin:0 auto;width: 100%;height: 100%"></div>
    <script type="text/javascript" include="leaflet.draw" src="../../dist/leaflet/include-leaflet.js"></script>
    <script src="https://unpkg.com/@geoman-io/leaflet-geoman-free@latest/dist/leaflet-geoman.min.js"></script>
    <link rel="stylesheet" href="https://unpkg.com/@geoman-io/leaflet-geoman-free@latest/dist/leaflet-geoman.css" />
    <script type="text/javascript">
        var map, url = "https://iserver.supermap.io/iserver/services/map-world/rest/maps/World";
        map = L.map('map', {
            crs: L.CRS.EPSG4326,
            center: [0, 0],
            maxZoom: 18,
            zoom: 1
        });
        new L.supermap.TiledMapLayer(url).addTo(map);
        
        function query(lat,lng,r) {
            // 利用传入的经纬度和半径值构造一个L.circle对象
            var circle = L.circle([lat,lng], {color: 'red',radius:r});
            // 借助circleToPolygon()方法,将L.circle转换为L.polygon,其中第二个参数为polygon边的数量
            var polygon = L.PM.Utils.circleToPolygon(circle, 600);
            var param = new L.supermap.QueryByGeometryParameters({
                queryParams: {name: "Capitals@World.1"},
                geometry: polygon
            });
            new L.supermap
                .QueryService(url)
                .queryByGeometry(param, function (serviceResult) {
                    var result = serviceResult.result;
                    var count = result.totalCount;
                    resultLayer = L.geoJSON(result.recordsets[0].features).addTo(map);
                    var popup = L.popup().setLatLng([lat,lng]).setContent('半径约为:'+ (r/1000).toFixed(2) +'千米
    结果数量:'
    +count+'个').openOn(map); }); } var editableLayers = new L.FeatureGroup(); map.addLayer(editableLayers); var options = { position: 'topleft', draw: { polyline: false, polygon: false, circle: {}, rectangle: false, marker: false, remove: false }, edit: { featureGroup: editableLayers, remove: false } }; var drawControl = new L.Control.Draw(options); map.addControl(drawControl); handleMapEvent(drawControl._container, map); map.on(L.Draw.Event.CREATED, function (e) { var type = e.layerType, layer = e.layer; if (type === 'marker') { layer.bindPopup('A popup!'); } editableLayers.addLayer(layer); // 获取绘制圆形的半径、圆心经纬度,并传入query()方法 var r = layer._mRadius; var lat = layer._latlng.lat; var lng = layer._latlng.lng; query(lat,lng,r); }); function handleMapEvent(div, map) { if (!div || !map) { return; } div.addEventListener('mouseover', function () { map.scrollWheelZoom.disable(); map.doubleClickZoom.disable(); }); div.addEventListener('mouseout', function () { map.scrollWheelZoom.enable(); map.doubleClickZoom.enable(); }); } </script> </body> </html>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92

    代码运行方式:
    ①在线编辑器:将完整代码复制到 SuperMap iClient 在线示例中运行;
    ②本地运行:保存完整代码为html文件,将其放置于iServer安装目录\iClient\forJavaScript\examples\leaflet,然后运行该示例。

  • 相关阅读:
    【Java并发编程七】Java内存模型
    单向链表(c/c++)
    Python灰帽编程——初识Python下(函数与文件)
    导师详解:多比特信号的CDC处理方式之异步FIFO
    c面向对象编码风格(上)
    Python 增量更新/打包解决方案 -- Depsland
    【Vue面试专题】50+道经典Vue面试题详解!
    包管理工具--》发布一个自己的npm包
    设计模式-桥接模式
    软件的生命周期(软件工程各阶段的工作)
  • 原文地址:https://blog.csdn.net/supermapsupport/article/details/128063672