openlayers 3 开发,点击 Overlay 请求WFS并进入下一级别(顺带解决上一次问题)

上次[http://blog.csdn.net/sinat_25295611/article/details/79110368] 遇到一个神奇的BUG,怀疑是openlayers这个版本中自动绘制 Text 的一个Bug,其他要素的Text背景样式失效了,一直没有解决。
于是换了另外一种方式来实现,也就是 使用 ol.Overlay 来添加标签。

当加载完Source要素的时候,获取每个要素的’name’属性,将其作为标签,这里需要注意一点的是,经常有人问怎么监听要素已经加载完毕,由于使用 ol.source.Vector 加载要素(wfs服务/geojson文件等等)是异步加载,所以,在代码中要给要素绑定事件的时候可能还没有该要素,比如下面这样:

    var map = new ol.Map({
        layers: [
            new ol.layer.Tile({
                source: new ol.source.OSM()
            })
        ],
        view: new ol.View({ 
            center: [-72.980624870461128, 48.161307640513321],
            zoom: 8,
            projection: 'EPSG:4326'
        }),
        target: 'map'
    });

    var vectorLayer = new ol.layer.Vector({
        source: new ol.source.Vector({
            url: '../data/geojson/line.geojson', 
            format: new ol.format.GeoJSON()
        })
    });
  map.addLayer(vectorLayer);
    // 如果在此处调用vectorLayer.getSource().getFeatures()是完全有可能获取不到任何Feature的

去查Openlayers的 API文档会看到 ol.source.Vector 有一个loader 的属性,并在后面有一段示例代码:

var vectorSource = new ol.source.Vector({
  format: new ol.format.GeoJSON(),
  loader: function(extent, resolution, projection) {
     var proj = projection.getCode();
     var url = 'https://ahocevar.com/geoserver/wfs?service=WFS&' +
         'version=1.1.0&request=GetFeature&typename=osm:water_areas&' +
         'outputFormat=application/json&srsname=' + proj + '&' +
         'bbox=' + extent.join(',') + ',' + proj;
     var xhr = new XMLHttpRequest();
     xhr.open('GET', url);
     var onError = function() {
       vectorSource.removeLoadedExtent(extent);
     }
     xhr.onerror = onError;
     xhr.onload = function() {
       if (xhr.status == 200) {
         vectorSource.addFeatures(
             vectorSource.getFormat().readFeatures(xhr.responseText));
       } else {
         onError();
       }
     }
     xhr.send();
   },
   strategy: ol.loadingstrategy.bbox
 });

后面一段说明:The loader function used to load features, from a remote source for example. If this is not set and url is set, the source will create and use an XHR feature loader.
也就是说,loader是一个函数用于加载数据源,但如果未设置,并且设置了url,就会用XHR异步请求来加载数据源。也就是说,我们完全可以用 loader 这个函数来代替 url ,在其中我们可以自定义的发送请求,然后在回调函数中,对获取的要素源进行处理。

于是用loader来给每个要素手工添加标签,当加载完Source要素的时候,获取每个要素的’name’属性,将其作为标签。就像这样:

var beijingSource=new ol.source.Vector({
                format: new ol.format.GeoJSON(),
                loader:function (extent,resolution,projection) {
                    var url='http://'+host+'/geoserver/wfs?' +
                        'service=wfs&version=1.1.0&request=GetFeature&typeNames=ztbr:beijing_pq&outputFormat=application/json&srsname=EPSG:3857';
                    $.ajax({
                        url:url,
                        type:'GET',
                        success:function (res) {
                            beijingSource.addFeatures(beijingSource.getFormat().readFeatures(res));
                            var features=beijingSource.getFeatures();
                            features.forEach(x =>{
                                //创建标签的函数,由于我采用的vue组件开发的,vm是我的Vue的this对象
                                vm.creatLabelForFeature(x,"beijing_pq");
                            });
                        },
                        error:function () {
                            alert("error")
                        }
                    })
                }
            });


//然后是创建标签的函数`creatLabelForFeature`

/** 1.根据传入的要素,添加对应的Lable。并在lable上绑定点击事件,点击lable可以进行缩放,请求下一级的矢量地图,同时隐藏lable   */
            creatLabelForFeature: function(feature,layerId) {
                var vm=this;
                var map=vm.map;
                var beijingLayer = vm.layers.beijing_pq;
                var jiedaoLayer = vm.layers.beijing_jd;
                var shequLayer = vm.layers.beijing_sq;

                var extent=feature.getGeometry().getExtent();
                var geom = feature.getGeometry();
                var pos=ol.extent.getCenter(extent);
                var content = feature.get('name');
                var ele=$("<div class='nameLabel'></div>");
                ele.attr("layerId", layerId);
                ele.html(content);
                ele.css({
                    'font-size':'12px',
                    'color': '#ffffff',
                    'background-color':'#4D98DD' ,
                    'cursor': 'pointer',
                    'padding':'1px 4px',
                    'border-radius': '4px'
                });

                //给ele 绑点点击事件,点击获取指定下一级的 wfs
                ele.click(function (evt) {
                    map.getView().fit(geom,map.getSize());
                    var lid = ele.attr("layerId");

                    var featureName = ele.html();
                    // console.log(featureName);
                    if(lid == 'beijing_pq'){
                        //点击北京区域图层,到指定区,加载街道
                        beijingLayer.setVisible(false);
                        jiedaoLayer.setSource(new ol.source.Vector());    //每次点击要把之前的 Source清空 fixme
                        vm.getWFS('beijing_jd', ol.format.filter.equalTo('district', featureName), jiedaoLayer);
                    }else if(lid == 'beijing_jd'){
                        //点击街道图层,到指定街道,加载社区
                        jiedaoLayer.setVisible(false);
                        shequLayer.setSource(new ol.source.Vector());
                        vm.getWFS('beijing_sq', ol.format.filter.equalTo('street', featureName),shequLayer);

                    }else if(lid == 'beijing_sq'){
                        //TODO 显示一个社区
                        shequLayer.setSource(new ol.source.Vector());
                        vm.getWFS('beijing_sq', ol.format.filter.equalTo('name', featureName),shequLayer);
                    }
                    //隐藏上一级的 Overlayers
                    vm.clearOverlayers(lid);
                });
                var label = new ol.Overlay({
                    position: pos,
                    positioning: 'center-center',
                    element: ele[0],
                    stopEvent: false
                });
                map.addOverlay(label);
                //标签的缓存数组,下次加载时直接取用
                vm.overlays[layerId].push(label);

            }

于是就实现了下面的效果:(这是鼠标移入移出时就没有了上篇文章中的Bug了。。。)

这里写图片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章