首页 文章

多层的Openlayers和事件(OpenLayer.Layer.Vector)

提问于
浏览
10

另一天与openlayers和另一个问题一起工作 .

即 - 我有多个矢量图层在彼此的顶部,用于不同类型的东西(汽车,历史和地区的旅行) . 他们都有我试图 grab 的事件......但是当Niklas发现时,当你在一个层上激活事件时,它会被移动到顶层,而下面层上的事件不会被触发 .

有没有办法绕过这个?因为当我移动区域多边形时,我希望事件触发并显示其名称,当我将鼠标移动到汽车标记时,我也希望事件发生火灾 . 并且不 - 我不想将它们放在同一层上,因为我希望它能够快速关闭或打开它们而不需要循环遍历所有功能并且每个功能都禁用它们 .

艾伦

Edit1:我做了一些搜索,发现你可以在多个图层上使用相同的控件 . 这可能对我来说可以解决这个问题 . 我正在检查它并测试是否向单个控件添加更多层是我的问题的解决方案 .

4 回答

  • 10

    当我遇到同样的问题时,我发现了这个问题,试图让多个层对鼠标事件做出反应 .

    解决方案,以防其他人发现此线程更简单 .

    SelectFeature控件采用Vector图层数组,如果您需要对鼠标事件(悬停和单击)做出反应的所有内容都在该数组中,则它们全部工作,而不仅仅是移动到顶部的那个 .

    因此,在该线程的批准解决方案中,通过这样做可以大大简化:

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

    这将在两个层上注册适当的事件并使它们都存在 .

    我希望这可以帮助其他人在这个问题上遇到麻烦 .

    正如其他地方所说的那样,使用OpenLayers并不难,找到正确的方法来处理它 .

  • 1

    这解决了我的问题:

    before :

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

    after :

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

    希望能帮助到你

  • 0

    那么解决方案是:

    /*
    * 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;
    };
    
  • 3

    我很荣幸被这样提到! :-)

    我最终在一个额外的js文件中覆盖了Feature Handler中的activate函数:(注释行是唯一的区别 . )

    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;
    };
    

    我还发现选择控件在层上不起作用,所以我认为在控件中使用多个层的方法看起来很好 .

相关问题