Wechat: yu389741| Email: gisdqy@163.com

Shop:https://www.giserdqy.com/shop

有关OpenLayers中ol.interaction.Translate的hitTolerance属性的问题


在使用OpenLayers的ol.interaction.Translate功能的时候,遇到了以下问题:

当hitTolerance不为0时(默认为0),在数据量较大时,地图交互出现了明显的延迟和卡顿:

this.select = new ol.interaction.Select(
{
	layers:[editableLayer],
});
Map.addInteraction(this.select);//将新建的Select对象加入map中

this.translate = new ol.interaction.Translate({
	features: this.select.getFeatures(),
	hitTolerance: 50,
});
Map.addInteraction(this.translate);

查看OL中有关Translate的源码发现,引用到hitTolerance的方法中,有这么一段代码

/**
 * Tests to see if the given coordinates intersects any of our selected
 * features.
 * @param {ol.Pixel} pixel Pixel coordinate to test for intersection.
 * @param {ol.PluggableMap} map Map to test the intersection on.
 * @return {ol.Feature} Returns the feature found at the specified pixel
 * coordinates.
 * @private
 */
ol.interaction.Translate.prototype.featuresAtPixel_ = function(pixel, map) {
  return map.forEachFeatureAtPixel(pixel,
      function(feature) {
        if (!this.features_ ||
            ol.array.includes(this.features_.getArray(), feature)) {
          return feature;
        }
      }.bind(this), {
        layerFilter: this.layerFilter_,
        hitTolerance: this.hitTolerance_
      });
};

featuresAtPixel_函数的目的是检测当前的坐标是否与选中的要素相交。仔细阅读源码就会发现,检测的方式是获取当前pixel下的feature,判断该feature是否属于选中的features。注意最后传入了两个参数:layerFilter和hitTolerance。layerFilter用于过滤图层,hitTolerance则用于设置检测的范围。简单来说,当hitTolerance为0时,只有pixel刚好包含于feature才会进行判断,随着hitTolerance增大,只要feature到当前pixel的距离在hitTolerance内,都会进行判断

继续查源码,发现了以下事件处理函数中使用到了featuresAtPixel_函数:

/**
 * @param {ol.MapBrowserEvent} event Event.
 * @this {ol.interaction.Translate}
 * @private
 */
ol.interaction.Translate.handleMoveEvent_ = function(event) {
  var elem = event.map.getViewport();

  // Change the cursor to grab/grabbing if hovering any of the features managed
  // by the interaction
  if (this.featuresAtPixel_(event.pixel, event.map)) {
    elem.classList.remove(this.lastCoordinate_ ? 'ol-grab' : 'ol-grabbing');
    elem.classList.add(this.lastCoordinate_ ? 'ol-grabbing' : 'ol-grab');
  } else {
    elem.classList.remove('ol-grab', 'ol-grabbing');
  }
};

该事件在鼠标移动的过程中触发,光标每次移出或进入Translate的features范围时改变光标样式。

以上是从外到内寻找问题的过程。那么我们现在可以从内到外梳理一下为什么会出现该问题:

在启用Translate功能后,OL始终会监测鼠标的移动状态并触发handleMoveEvent事件处理函数。该函数调用featuresAtPixel_方法,改变光标的样式。而在featuresAtPixel_函数中,每次鼠标移动导致pixel发生变化,都会检测hitTolerance内的每个要素是否属于被选中的要素。随着hitTolerance的增大和要素数量的增多,函数的执行次数会急剧增长。

handleMoveEvent function |undefined

Function handling “move” events. This function is called on “move” events,also during a drag sequence (so during a drag sequence both the handleDragEvent function
and this function are called).

另外,通过查看ol.interaction.Pointer的说明可以看到,handleMoveEvent在鼠标drag的过程中也会触发!


总结:在鼠标移动(包括drag操作)的过程中总会调用featuresAtPixel_函数,随着hitTolerance的增大和要素数量的增多,函数的执行次数会急剧增长了解了该问题后,我们就知道如何解决或者说缓解该问题了:减小数据量或减小hitTolerance。加一句,减小数据量的意思是减小前端展示出来的数据量。可以通过隐藏图层的方式减少数据量。

转载自:https://blog.csdn.net/a20100997/article/details/78979061