【问题标题】:Openlayers and events on multiple layers (OpenLayer.Layer.Vector)多层上的 Openlayers 和事件 (OpenLayer.Layer.Vector)
【发布时间】:2011-04-08 11:33:28
【问题描述】:

又一天使用 openlayers 和另一个问题。

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

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

艾伦

Edit1:我做了一些搜索,发现您可以在多个图层上使用相同的控件。这可能会为我解决这个问题。我正在检查 atm 并测试向单个控件添加更多层是否可以解决我的问题。

【问题讨论】:

    标签: events openlayers


    【解决方案1】:

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

    解决方案,以防万一其他人发现这个线程要简单得多。

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

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

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

    这将在两个层上注册适当的事件并使它们都处于活动状态。

    我希望这可以帮助其他遇到此问题的人。

    正如其他地方所说,使用 OpenLayers 并不难,找到使用它的正确方法就可以了。

    【讨论】:

    【解决方案2】:

    这解决了我的问题:

    之前:

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

    之后:

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

    希望对你有帮助

    【讨论】:

      【解决方案3】:

      这就是解决方案:

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

      【讨论】:

      • 看起来令人印象深刻! OpenMap 是什么类型的对象?
      • 只有一个 blob 对象来处理我(或任何访问者)在地图页面上所做的一切。在这个方法中,我现在将事件绑定到特性。在下一个方法中,我将不同的 jQuery 事件绑定到不同的 dom 元素。然后有一个方法是 jQuery.ajax 的包装器,因此所有 ajax 调用都通过一个方法,该方法具有成功和错误回调作为其参数......等等。基本上我认为创建一个大对象比创建一大堆函数更好,这些函数都将地图作为一个参数接收。
      • 其实……写完这个方法后我不得不更新它。但是,这些变化是针对我的情况的。对于其他需要解决相同问题的人来说,这里的例子应该足够了:)
      【解决方案4】:

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

      我最终在另一个 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;
      };
      

      我还发现选择控件在不在顶部的图层上工作,所以我认为您在控件中使用多个图层的方法看起来不错。

      【讨论】:

      • 嗯……这对我来说不会有用,我害怕。我仍在研究在多个图层上使用相同的选择控件。看起来很有希望。如果我完成了,我会发布解决方案:P
      • 您现在可以查看 :)。实际上.. 使用 OpenLayers 并不难...找到正确的做事方式是 H A R D!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-31
      • 1970-01-01
      相关资源
      最近更新 更多