Очистить слой WMS перед перерисовкой на OpenLayers

В настоящее время я успешно отображаю несколько слоев с помощью OpenLayers (Vector и WMS). Мое приложение позволяет пользователю изменять некоторые параметры, которые:
* изменяют привязку
* изменяют центр карты
* изменяют изображение WMS
Я использую Ajax, чтобы избежать перезагрузки страницы, однако он работает нормально когда некоторым слоям требуется время для загрузки, другие, которые еще не перерисованы, по-прежнему отображаются в фоновом режиме (но никак не связаны с моим новым контекстом). Я хотел бы очистить слои WMS (если возможно), прежде чем повторно запрашивать у сервера новое изображение, но пока ничего не нашел. Я делаю это на векторном слое, вызывая removeAllFeature ();

Спасибо за любую помощь!

Вот мой псевдокод, когда пользователь нажимает кнопку:

$.getJSON("url/updateMapConfig.php",
    {  
      data: $(this).serialize() ,   
      ajax: 'true',   
      cache: 'false'  
    },   
    function(j){  
      if (j.result == 'ok') {  
        var layersToShow = [];  
        // Refresh vector layer  
        for(var i=0;i<map.layers.length;i++) {  
          if (map.layers[i].isVector) {  
            map.layers[i].removeAllFeatures();  
            map.layers[i].refresh({force:true}); // Vector layer  
          }   
        }  
        // Refresh visible layers  
        for(var i=0;i<map.layers.length;i++) {  
          if (map.layers[i].visibility && !map.layers[i].isBaseLayer && !map.layers[i].isVector) { // Refresh visible non base  
              map.layers[i].redraw(true); // Other layer  
          }  
        }  
        // Set new bounds  
        var bounds = new OpenLayers.Bounds();  
          bounds.extend(new OpenLayers.LonLat(j.bounds.xmin-100, j.bounds.ymin-100));  
          bounds.extend(new OpenLayers.LonLat(parseInt(j.bounds.xmax)+100, parseInt(j.bounds.ymax)+100));  
        map.zoomToExtent(bounds);  
        // Move to destination point  
        if (j.poiCenter != "") {  
          eval("map.setCenter(new OpenLayers.LonLat("+j.poiCenter+"))");  
        }  
      }  
    }  
);  

person Michael Laffargue    schedule 10.02.2011    source источник


Ответы (3)


Я бы использовал mergeNewParams, чтобы установить параметр, при котором слой будет пустым. Этот метод вызывает перерисовку слоя. Когда ваш обратный вызов возвращается из вашего запроса на обновление, вы делаете обратное, чтобы он снова правильно рисовал слой.

(Я сделал что-то подобное, но пока у меня нет источника)

РЕДАКТИРОВАТЬ:

Или, конечно, скройте слои с помощью видимости свойство слоев. :-)

person Niklas Wulff    schedule 10.02.2011
comment
Спасибо, попробовал сделать: map.layers [i] .setVisibility (false); map.layers [i] .setVisibility (истина); Тем не менее, слой все еще остается, пока он не перерисовывается, как ни странно. Попробую mergeNewParams - person Michael Laffargue; 11.02.2011
comment
Может надо при настройке видимости принудительно перерисовывать? Хотя это кажется маловероятным ... - person Niklas Wulff; 11.02.2011
comment
При более внимательном рассмотрении вашего кода я не вижу кода, который очищает или скрывает растровые слои. Ваша функция (j) является обработчиком успеха, но где вы обновляете конфигурацию карты? Может я этого не понимаю ... - person Niklas Wulff; 11.02.2011
comment
Технически мой WMS-сервер генерирует данные в пользовательском SESSION, поэтому я отправляю Ajax-запрос, который изменяет пользовательский SESSION. После этого я просто перерисовываю слои (для (var i = 0; i ‹map.layers.length; i ++) {). - person Michael Laffargue; 11.02.2011
comment
В порядке. Но я не вижу кода, который пытается скрыть слои до вызова redraw (). Где ты это делаешь? - person Niklas Wulff; 11.02.2011
comment
Вы правы, его нет в этой версии (как я пробовал после вашей рекомендации). Теперь я: скрыть весь видимый слой (и сохранить список в массиве), изменить границы / центр, перерисовать эти слои и затем показать их обратно. Для больших слоев я получил этот глюк, при котором часть старого изображения показывается в течение 2/3 с. - person Michael Laffargue; 11.02.2011

Я наконец обнаружил счастливый конец, используя функцию clearGrid () на каждом слое перед их перерисовкой.

Я также обнаружил, что эта функция остановит загрузку плитки, если она запущена. Пример У меня было два базовых слоя: EmptyLayer и WhateverTiledBGLayer. если ему потребуется 20 секунд для загрузки плиток WhateverTiledBGLayer, даже если пользователь выбрал переключение на пустой слой, я мог бы увидеть запрос, сделанный серверу для оставшихся плиток на WhateverTiledBGLayer.

Простой вызов WhateverTiledBGLayer.clearGrid () перестанет запрашивать слои.

Спасибо за помощь.

person Michael Laffargue    schedule 22.02.2011

Вы можете прослушивать события loadstart и loadend слоя WMS и соответственно скрывать / отображать слой.

Однако быстрый тест показал, что вы не можете установить для видимости слоя значение false при загрузке, потому что тогда OpenLayers перестанет запрашивать новые изображения для слоя, и он никогда не будет загружен полностью. Вы могли бы хотя бы попробовать с layer.display (false / true) и посмотреть, решит ли он вашу проблему. Код должен выглядеть примерно так:

  yourWmsLayer.events.on({
        "loadstart" : function(){
            this.display(false);
        },
        "loadend" : function(){
            this.display(true);
        } 
    });

Кстати, если вы не установите для transitionEffect значение «изменение размера» на слое WMS, то по умолчанию старые изображения удаляются перед загрузкой новых. Разве ты не этого хочешь?

person igorti    schedule 11.02.2011
comment
Спасибо за ответ, у меня нет transitionEffect, но старое изображение не удалено, я попробую решение Niklas, а затем ваше, если оно не поможет. - person Michael Laffargue; 11.02.2011
comment
Хорошо, я попробовал оба решения, и поведение не изменилось, однако я обнаружил, что мое объяснение проблемы не очень хорошее. Фактически, слой скрыт, затем запускается событие loadend и слой снова появляется. Но проходит некоторое время после события, прежде чем слой покажет новое изображение (1000x600). И за это время показывается часть старого изображения. - person Michael Laffargue; 11.02.2011
comment
тогда вы можете попробовать добавить таймер, чтобы вы установили this.display (true) через несколько секунд после срабатывания loadend. Что-то вроде этого внутри обратного вызова loadend - setTimeout (this.display (true), 3000); - person igorti; 11.02.2011