Openlayers и события на нескольких слоях (OpenLayer.Layer.Vector) - PullRequest
10 голосов
/ 08 апреля 2011

Еще один день работы с openlayers и еще одна проблема.

А именно - у меня есть несколько векторных слоев друг на друге для разных типов вещей (автомобили, поездки из истории и областей). У них всех есть события, которые я пытаюсь поймать ... Но, как выяснилось Niklas , когда вы активируете события на одном слое, он перемещается сверху, а события на слоях ниже не срабатывают.

Есть ли способ обойти это? Потому что, когда я перемещаюсь по полигону области, я хочу, чтобы событие запускалось и отображало его имя, а когда я перемещаю курсор мыши к маркеру автомобиля, я хочу, чтобы событие тоже запускалось. И нет - я не хочу размещать их на одном слое, потому что я хочу, чтобы можно было их быстро отключить или включить, не просматривая все функции и не отключая каждый из них.

Alan

Edit1: я провел поиск и обнаружил, что вы можете использовать один и тот же элемент управления на нескольких слоях. это могло бы решить эту проблему для меня. Я проверяю его и проверяю, является ли добавление нескольких слоев в один элемент управления решением моей проблемы.

Ответы [ 4 ]

10 голосов
/ 18 сентября 2012

Я обнаружил это, когда столкнулся с той же проблемой, пытаясь заставить несколько слоев реагировать на события мыши.

Решение, на случай, если кто-то еще найдет эту ветку, намного проще.

Элемент управления SelectFeature принимает массив векторных слоев, и если все последующие элементы, которые вам нужно реагировать на события мыши (при наведении и щелчке), находятся в этом массиве, они ВСЕ работают, а не только тот, который был перемещен наверх.

Таким образом, в утвержденном решении для этой темы, это может быть значительно упрощено следующим образом:

this.carSelect = new OpenLayers.Control.SelectFeature(
    [this.vectorsLayer, this.carsLayer],
    {
        'hover':true,
        'callbacks': {
            blah blah blah
    }
});

Это позволит зарегистрировать соответствующие события на обоих слоях и активировать их оба.

Надеюсь, это поможет кому-то еще оступиться в этом вопросе.

Как сказано в другом месте, использование OpenLayers не сложно, найти правильный способ сделать что-то с ним.

3 голосов
/ 16 февраля 2012

это решит мою проблему:

до:

      map.addLayer(layer);
      layer.events.register("loadend", layer, function(){
        $("#progress").hide();
      });

после:

      layer.events.register("loadend", layer, function(){
        $("#progress").hide();
      });
      map.addLayer(layer);

Надеюсь, это поможет

1 голос
/ 10 апреля 2011

Ну вот решение:

/*
* This method will be called each time you add more vector layers to your map.
* i get more data with ajax calls and some of this data will go to existing layers,
* some of it will go to new layers... Some layers will be added and some removed. 
*/

OpenMap.prototype.bindFeatureEvents = function (arr){
    var that = this;
    if ( this.initialized == true ){
    /* if map is already initialized we deactivate and remove control - 
    * we will re add it later. I havent tested if its really necessary...
    */
        this.carSelect.deactivate();
        this.mymap.removeControl(this.carSelect);
    } else {
        this.carSelect = new OpenLayers.Control.SelectFeature([], {
            'hover':true,
            'callbacks':{
                'click':function(f){
                    if ( typeof f.attributes.data.id != 'undefined'){
                        that.selectCar(f.attributes.data.id);
                    }
                }
        }});

        this.vectorsLayer.events.on({
            'featureselected': this.onFeatureSelect.bind(this),// these methods open and close popups.
            'featureunselected': this.onFeatureUnselect.bind(this)
        });

        this.carsLayer.events.on({
            'featureselected': this.onFeatureSelect.bind(this),
            'featureunselected': this.onFeatureUnselect.bind(this),
            'moveend': function(e) {
                if (e.zoomChanged) {
                    if (this.watchCar == true){
                        this.holdZoom = true;
                    }
                }
             }.bind(this)//without this the "this" in moveend callback is openlayers.layer.vector
        });
        /*
        * I save existing layers in two arrays... It seemed simpler to use two arrays.. 
        * or you could of course use one Object instead of two Arrays... 
        * and you really need to bind events to each layer only once... otherwise each rebinds
        * makes events firing more and more. 
        * each time bindFeatureEvents is called.. new events would be added.
        */
        var name = this.vectorsLayer.name;
        this.boundLayers.push(name)
        this.allLayers.push(this.vectorsLayer);
        var name = this.carsLayer.name;
        this.boundLayers.push(name)
        this.allLayers.push(this.carsLayer);
        this.initialized = true;
    }
    /*
    * We need to check if any arr was provided at bindFeatureEvents call. 
    * if not.. then ohwell. pass :P
    */
    if ( arr != null && typeof(arr)=='object' && arr instanceof Array && arr.length > 0 ){
        for ( i = 0 ; i < arr.length; i++){
            var name = arr[i].name;
            if ( name in oc(this.boundLayers) ){
                 // Tell me how to skip this part... 
            } else {
            //we add new layer to both arrays.
                this.boundLayers.push(name);
                this.allLayers.push(arr[i]);
            }
        }
    }
    /*
    * this next line is what made it sensible to use two arrays... you can
    * feed all layers easyer to setLayer method
    * We could also use bit of code to check if some layers were removed... 
    */
    this.carSelect.setLayer(this.allLayers);
    this.mymap.addControl(this.carSelect);
    this.carSelect.activate();
    /*
    * Yeah the control is acitvated again and the events are firing on all layers...
    */
};

//taken from http://snook.ca/archives/javascript/testing_for_a_v
function oc(array){
    var o = {};
    for(var i=0;i<array.length;i++){
        o[array[i]]='';
    }
    return o;
};
0 голосов
/ 08 апреля 2011

Для меня большая честь быть упомянутой так!: -)

Я закончил тем, что переопределил функцию активации в Feature Handler в дополнительном js-файле: (Комментированная строка - единственное отличие.)

OpenLayers.Handler.Feature.prototype.activate = function() {
    var activated = false;
    if (OpenLayers.Handler.prototype.activate.apply(this, arguments)) {
        //this.moveLayerToTop();
        this.map.events.on({
            "removelayer": this.handleMapEvents,
            "changelayer": this.handleMapEvents,
            scope: this
        });
        activated = true;
    }
    return activated;
};

Я также обнаружил, чтоЭлементы управления select работали со слоями, не находящимися сверху, поэтому я думаю, что ваш подход с использованием нескольких слоев в элементе управления выглядит хорошо.

...