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" />

(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);

(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) +'千米<br/>结果数量:'+count+'个').openOn(map);
            });
    }

(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);

(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);
    });

【完整代码】

<!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) +'千米<br/>结果数量:'+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>

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

  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值