开源GIS(七)——openlayers中单击获取要素(深度好文)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/xcymorningsun/article/details/82492384

目录

 

 

一、引言

 

二、前台方法

 

1、interaction中select方法

 

2、map中forEachFeatureAtPixel方法

 

三、gis server方法

 

1、wms中getfeatureinfo

 

2、wfs中getfeature

 

四、后台方法

 

五、空间数据库方法

 

六、总结

 


 

一、引言

 

以前在做arcgis js开发的时候,就开始纠结单击获取要素使用哪种方法,当时是因为arcgis server正好提供了arcgis定制的服务IdentifyTask,所以当时用了arcgis server查询的。

总结一下查询方法有如下几种:

这四种各有优缺点,下面详细介绍前两种方法,后面两种方法涉及到的知识比较多,不方便展开,仅提供思路==

 

二、前台方法

 

1、interaction中select方法

 

针对矢量数据源,openlayers中提供了select交互类方面鼠标选择。

    /*overlay*/
    // Popup showing the position the user clicked
    var popup = new ol.Overlay({
        element: document.getElementById('popup'),
        autoPan:true,
        autoPanMargin:100,
        positioning:'center-right'
    });
    map.addOverlay(popup);

    /*select*/
    var selectSingleClick = new ol.interaction.Select();
    map.addInteraction(selectSingleClick);
    /*前端第一种*/
    selectSingleClick.on('select', function(e) {
        var features=e.target.getFeatures().getArray();
        var element = popup.getElement();
        if (features.length>0)
        {
            var feature=features[0];
            var type=feature.getGeometry().getType();
            var property=feature.getProperties();
            var coordinate = ol.extent.getCenter(feature.getGeometry().getExtent());
            var hdms="点名:"+property["Text"];
            hdms=hdms+"<br/>";
            hdms = hdms+"图层名::"+property["Layer"];
            hdms=hdms+"<br/>";
            hdms = hdms+"位置:"+coordinate[0]+"-"+coordinate[1];

            $(element).popover('destroy');
            popup.setPosition(coordinate);
            // the keys are quoted to prevent renaming in ADVANCED mode.
            $(element).popover({
                'placement': 'top',
                'animation': false,
                'html': true,
                'content': hdms
            });
            $(element).popover('show');
        }
        else
        {
            $(element).popover('destroy');

        }

    });

这里popup是个overlay覆盖物,用于弹出框显示得到的feature要素。

 

2、map中forEachFeatureAtPixel方法

 

针对矢量数据源,通过鼠标点击坐标与map坐标对比,获取选中要素,openlayers提供了相关函数。

    /*前端第二种*/
    map.on("click", function(e) {
        var element = popup.getElement();
        $(element).popover('destroy');
        map.forEachFeatureAtPixel(e.pixel, function (feature, layer) {
            //do something
            var type=feature.getGeometry().getType();
            var property=feature.getProperties();
            var coordinate = ol.extent.getCenter(feature.getGeometry().getExtent());
            var hdms="点名:"+property["Text"];
            hdms=hdms+"<br/>";
            hdms = hdms+"图层名::"+property["Layer"];
            hdms=hdms+"<br/>";
            hdms = hdms+"位置:"+coordinate[0]+"-"+coordinate[1];

            $(element).popover('destroy');
            popup.setPosition(coordinate);
            // the keys are quoted to prevent renaming in ADVANCED mode.
            $(element).popover({
                'placement': 'top',
                'animation': false,
                'html': true,
                'content': hdms
            });
            $(element).popover('show');
        })
    });

这里省略了popup,与上个例子中类似。

 

三、gis server方法

 

1、wms中getfeatureinfo

 

针对没有显示到地图上,但是有wms的图层数据,我们可以使用getfeatureinfo从geoserver(或者其他支持wms的gis服务器)获取要素,这个是跟ogc标准相关的,与具体的gis服务器无关。

  var format = 'image/png';
    var wmsLayer = new ol.layer.Tile({
        //visible: false,
        source: new ol.source.TileWMS({
            url: 'http://localhost:8080/geoserver/xcy/wms',
            params: {'FORMAT': format,
                'VERSION': '1.1.1',
                tiled: true,
                "STYLES": '',
                "LAYERS": 'xcy:polygon'
                //"exceptions": 'application/vnd.ogc.se_inimage',
                //tilesOrigin: 8176078.237520734 + "," + 704818.0275364731
            },
            serverType: 'geoserver',
            crossOrigin: 'anonymous'
        })
    });

    map.on('singleclick', function(evt) {
        document.getElementById('info').innerHTML = '';
        var viewResolution = /** @type {number} */ (view.getResolution());
        var url = wmsLayer.getSource().getGetFeatureInfoUrl(
            evt.coordinate, viewResolution, 'EPSG:3857',
            {'INFO_FORMAT': 'application/json'});
        var element = popup.getElement();
        $(element).popover('destroy');

        if (url) {
            $.ajax({
                type: "GET",
                url: url,
                dataType:'json',
                //data: {id:1001},//也可以是字符串链接"id=1001",建议用对象
                success: function(data){
                    console.log("返回的数据: " + data.features[0].properties.Layer);
                    var layer=data.features[0].properties.Layer;
                    var hdms = "图层名::"+layer;

                    $(element).popover({
                        'placement': 'top',
                        'animation': false,
                        'html': true,
                        'content': hdms
                    });
                    popup.setPosition(evt.coordinate);
                    $(element).popover('show');
                }
            });

        }
    });

首先获取wms的当前图层,然后拼接wms服务getfeatureinfo的url拼接,这里使用的函数获取,也可以直接按照ogc标准自己拼接url。

 

2、wfs中getfeature

 

针对没有显示到地图上但是有wfs服务的图层数据,可以使用getfeature的方法从gis服务器中获取要素信息,只要服务器提供ogc标准的wfs服务即可,它与wms的区别是wms中getfeatureinfo只是通过点获取要素信息,方法比较单一,而wfs中getfeature可以使用filter进行复杂的空间查询和属性查询,还可以通过bbox过滤空间信息。

 /*gis server第二种*/
    map.on('click',mapClick);
    //点击地图查询
    function mapClick(evt)
    {
        var element = popup.getElement();
        $(element).popover('destroy');

        var coor=evt.coordinate;
        coor=coor.join(',');
        //注意这里直接将点坐标提交,与图层做intersrct分析,对于面图层是没关系的。如果是查询,点或者线图形,一定要将coor先设置一个容差,经行buffer之后的图形,再去与图层叠加分析。不设置容差几乎就找不到了
        //图层的图形字段是geom,不同图层的图形字段都要自己先看下自己的,有的是the_geom,有的是shape等等,具体分析即可。
        var filter='filter=<Filter xmlns="http://www.opengis.net/ogc" xmlns:gml="http://www.opengis.net/gml"><Intersects><PropertyName>the_geom</PropertyName><gml:Point><gml:coordinates>'+coor+'</gml:coordinates></gml:Point></Intersects></Filter>'

        $.ajax({
            type: "GET",
            //url: "http://localhost:8080/geoserver/xcy/wfs?service=WFS&request=GetFeature&version=1.1.0&typename=xcy:polygon&outputFormat=json&CQL_FILTER=EntityHand='7E25'",
            //属性查询
            //url: "http://localhost:8080/geoserver/xcy/wfs?service=WFS&request=GetFeature&version=1.1.0&typename=xcy:polygon&outputFormat=json&PROPERTYNAME=Layer&FEATUREID=polygon.2",
            //空间查询
            url: 'http://localhost:8080/geoserver/xcy/wfs?service=WFS&request=GetFeature&version=1.1.0&typename=xcy:polygon&outputFormat=json&'+filter ,

            dataType:'json',
            success: function(data){
                console.log("返回的数据: " + data.features[0].properties.Layer);
                 var layer=data.features[0].properties.Layer;
                 var hdms = "图层名::"+layer;

                 $(element).popover({
                 'placement': 'top',
                 'animation': false,
                 'html': true,
                 'content': hdms
                 });
                 popup.setPosition(evt.coordinate);
                 $(element).popover('show');
            }

        });
    }

前两个url是属性查询,使用的url是通过filter进行一个点的空间查询,详细wfs服务可以查看http://docs.opengeospatial.org/is/04-094r1/04-094r1.html#118

空间查询还是比较复杂的,filter中的xml还需详细理解一下。

 

四、后台方法

 

最近出了个红芯浏览器,用的谷歌的内核,包装了下外表就说自主研发的,让人啼笑皆非,不过在码农的世界里没有利益,有现成的可以解决问题还是要善于借鉴的,这里可以使用AE或者geotool。

AE是arcgis的,C#阵营可以使用;geotool是开源的,java阵营比较方便。

 

首先使用正常的web框架,将点击坐标参数传到后台,用geojson或者自定义字符串随意,只要你能解析出来;

后台集成了AE或者geotool之后可以通过里面的空间分析或者属性分析工具,查出要查询的要素;

最后使用json返回,格式你自己定咯;

 

 

五、空间数据库方法

 

这种方法与后台方法类似,县将点击坐标参数传到后台,只不过没有使用的AE或者geotool来进行空间分析,而是直接使用空间数据库中的空间查询sql语句来查询数据,然后提交到后台,后台提交到前台显示。

执行sql如下: select * from t where ST_Intersect(t.geom,ST_GeomfromText('Point(x y)',3857));

 

六、总结

 

这几种方法没有绝对的好与坏,只是适合不适合的问题。

  • 前台:矢量数据,必须加载到地图,如果没有加载或者是wms就不可以了。这种方法比较方便,仅学习openlayers就可以,但是换了前端js框架就完戏;

 

  • gis server:数据发布为wms或者wfs,不必须加载到地图。可以看作提供地图数据的普通server,只要数据被发布就可以查询到,而且符合ogc标准,许多外部的数据可以为我所用;

 

  • 后台:提供接口,不必须加载到地图,相当于使用第三方库做了一个gis server。不符合ogc发布标准,但是定制化程度高,不过依赖第三方库,不用gis server发布数据,AE还要收费的;

 

  • 空间数据库:提供接口,不必须加载到地图,相当于在空间数据库基础上做了gis server。不符合ogc发布标准,定制化程度高,不依赖第三方库,不用gis server发布数据,需要数据库空间拓展,相对于后台方法比较适合处理大量数据,一个点击事件用数据库有点高射炮打蚊子了==

 

一个点击获取要素搞这么多种方法,有必要搞得这么复杂么?是的,单独从解决问题的角度我们并没有必要这么做,但是从这个过程中锻炼的是一种思想,数据从前台、后台、普通server、gis server、数据库等获取的各种手段,这个不仅在点击事件有这么多种方法,往大里讲整个系统架构也无非是这么几种。

 

 

 

 

阅读更多

扫码向博主提问

gis_morningsun

有所付出,有所收获
  • 擅长领域:
  • WebGIS
  • openlayers
  • geoserver
  • arcgisjs
  • javaweb
去开通我的Chat快问
换一批

没有更多推荐了,返回首页