• 聊聊iClient for Leaflet坐标转换问题


    作者:非法小恋

    背景

    SuperMap iClient for JavaScript 9D产品想必大伙都用了一段时间了,针对新推出的三款客户端产品,Leaflet,OpenLayaers,MapboxGL,各自的特点,之前的文章也都有聊。

    Leaflet:http://blog.csdn.net/supermapsupport/article/details/78403044
    Openlayers:http://blog.csdn.net/supermapsupport/article/details/78952736
    MapboxGL:http://blog.csdn.net/supermapsupport/article/details/78343391

    今天我们重点聊聊Leaflet坐标转换问题。前一段时间在开发过程中,发现Leaflet针对非4326坐标系(WGS84),不管是在展示上,还是绘制上都有所不便,今天我们就聊聊如何来做针对非4326坐标系地图与数据进行开发。
    (本章节范例所使用的范例数据为iServer产品包中自带China数据,EPSG3857投影)

    先看看我们要做什么

    先看效果:

    用户需求:使用Leaflet开发,拉框查询,将查询结果叠加展示在地图上。
    看似简单的需求,如果是在WGS84地图上实现,只需要3步搞定:

    • 1.添加绘制控件
    • 2.将绘制结果传入几何对象查询
    • 3.将查询结果解析,并在地图上展示

    但是我们如果在非WGS84地图上开发这个功能,就有些麻烦了,我们需要进行坐标转换操作,
    因为Leaflet规定:Mark展示,鼠标绘制操作等内容,都需传入经纬度信息,而非投影信息。
    通俗讲:就是绘制出来的对象,不能直接进行查询,需要坐标转换,我们需要以下几个步骤:

    • 1.添加绘制控件
    • 2.将绘制结果进行坐标转换
    • 3.将转换后的图形传入几何对象查询
    • 4.将查询结果解析,再次进行坐标转换
    • 5.将转换后的坐标,在地图上展示

    开发代码

    1.首先动态引入我们的Leaflet.draw控件,另在代码中我们只保留rectangle,绘制矩形操作。

    <script type="text/javascript" include="leaflet.draw" src="../../dist/include-leaflet.js"></script>
    
    
    var editableLayers = new L.FeatureGroup();
    map.addLayer(editableLayers);
     var options = {
         position: 'topleft',
         draw: {
             polyline: false,
             polygon: false,
             circle: false,
             rectangle: {},
             circlemarker:false,
             marker: false,
             remove: false
         },
         edit: {
             featureGroup: editableLayers,
             remove: false
         }
     };
     var drawControl = new L.Control.Draw(options);
    

    并添加绘制触发事件方法

     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);
            //这里就能触发绘制完成后返回内容
            //....
    
     });
    

    2.将绘制结果进行坐标转换,其中的关键代码L.CRS.EPSG3857.project(point_old);就是将绘制的4326地理坐标转换为3857投影坐标系

    //将绘制对象点拆分转换
    var polygonPoints = []; 
    for(var i = 0; i <  e.layer._latlngs[0].length; i++){
         var point_old = L.latLng(e.layer._latlngs[0][i].lat,e.layer._latlngs[0][i].lng);
         var point_new = L.CRS.EPSG3857.project(point_old);
         var point = [point_new.y, point_new.x];
         //var point = L.point(point_new.x, point_new.y);
         console.log(point);
         polygonPoints.push(point);
        
     }
     var polygon = L.polygon([polygonPoints]);
    

    3.将转换后的图形传入几何对象查询

    //查询
    var param = new SuperMap.QueryByGeometryParameters({
         queryParams: {name: "China_ProCenCity_pt@China"},
         geometry: polygon
     });
    
     L.supermap
     .queryService(url)
     .queryByGeometry(param, function (serviceResult) {
         //查询后的返回结果
     });
    

    4..将查询结果解析,再次进行坐标转换,转换成Leaflet需要的,并展示在地图上

    L.supermap
    .queryService(url)
    .queryByGeometry(param, function (serviceResult) {
        var result = serviceResult.result;
        resultLayer = L.featureGroup().addTo(map);
        for(var i = 0; i <result.recordsets[0].features.features.length;i++){
            var p = result.recordsets[0].features.features[i];
            var latlng = L.point(p.geometry.coordinates[0],p.geometry.coordinates[1]);
            //坐标转换
            var marker1 = L.marker(L.CRS.EPSG3857.unproject(latlng))
            resultLayer.addLayer(marker1);
    
        }
    });
    

    最终完成该功能

    (转发请注明出处:http://www.cnblogs.com/zhangyongli2011/ 如发现有错,请留言,谢谢)

    附上完整代码:

    1. 可将以下代码保存成一个html文件,放在iClientforJavaScriptexamplesleaflet目录中,然后运行。
    2. 复制在在线编辑器中运行,例如:http://iclient.supermapol.com/examples/leaflet/editor.html#01_tiledMapLayer4326
    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title data-i18n="resources.title_drawFeatures"></title>
        <script type="text/javascript" src="../js/include-web.js"></script>
    </head>
    <body style=" margin: 0;overflow: hidden;background: #fff; 100%;height:100%;position: absolute;top: 0;">
    <div id="map" style=" 100%;height:100%"></div>
    <script type="text/javascript" include="leaflet.draw" src="../../dist/include-leaflet.js"></script>
    <script type="text/javascript">
        var host = window.isLocal ? window.server : "http://support.supermap.com.cn:8090";
        var map, url = host + "/iserver/services/map-china400/rest/maps/China";
        map = L.map('map', {
            center: [33, 114],
            zoom: 4
        });
        L.supermap.tiledMapLayer(url).addTo(map);
    
        var editableLayers = new L.FeatureGroup();
        map.addLayer(editableLayers);
        var options = {
            position: 'topleft',
            draw: {
                polyline: false,
                polygon: false,
                circle: false,
                rectangle: {},
                circlemarker: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);
    
            //将绘制对象点拆分转换
            var polygonPoints = []; 
            for(var i = 0; i <  e.layer._latlngs[0].length; i++){
                var point_old = L.latLng(e.layer._latlngs[0][i].lat,e.layer._latlngs[0][i].lng);
                var point_new = L.CRS.EPSG3857.project(point_old);
                var point = [point_new.y, point_new.x];
                //var point = L.point(point_new.x, point_new.y);
                console.log(point);
                polygonPoints.push(point);
               
            }
            var polygon = L.polygon([polygonPoints]);
            //查询
            var param = new SuperMap.QueryByGeometryParameters({
                queryParams: {name: "China_ProCenCity_pt@China"},
                geometry: polygon
            });
    
            L.supermap
            .queryService(url)
            .queryByGeometry(param, function (serviceResult) {
                var result = serviceResult.result;
                resultLayer = L.featureGroup().addTo(map);
                for(var i = 0; i <result.recordsets[0].features.features.length;i++){
                    var p = result.recordsets[0].features.features[i];
                    var latlng = L.point(p.geometry.coordinates[0],p.geometry.coordinates[1]);
                    //坐标转换
                    var marker1 = L.marker(L.CRS.EPSG3857.unproject(latlng))
                    resultLayer.addLayer(marker1);
    
                }
            });
          
    
        });
    
        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>
    
  • 相关阅读:
    poj 3264 Balanced Lineup
    poj 2762 Going from u to v or from v to u?
    hdu 3671 Boonie and Clyde
    zoj 3195 Design the city
    poj 1523 SPF
    Codeforces Polo the Penguin and Matrix
    MVC原理的简述(转)
    C#访问权限修饰符
    XML Schema介绍
    Sql批量删除/插入
  • 原文地址:https://www.cnblogs.com/zhangyongli2011/p/8582127.html
Copyright © 2020-2023  润新知