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了。。。)

這裏寫圖片描述

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