【问题标题】:OpenLayers Inconsistent Hit Detection on MVT Layer Hover SelectionOpenLayers 在 MVT 层悬停选择上的不一致命中检测
【发布时间】:2022-01-24 14:06:19
【问题描述】:

目标

我正在尝试从 OpenLayers 站点复制 this example 中的“单选悬停”功能。

问题

当我尝试使用此实现时,vtLayer.getFeatures(event.pixel) 的命中检测非常差。 documentation for the function 声明:

用于此方法的命中检测算法针对性能进行了优化,但不如 map.getFeaturesAtPixel() 中使用的算法准确

确实,当我切换到map.getFeaturesAtPixel 时,性能有所提高,但功能仍然无法完全按预期工作。

当我将指针从外部移到矢量边界上时,它(通常)会按预期运行:

但是,当我移动到相邻边界然后返回时,该功能不再起作用:

我的代码:

proj4.defs(
  'EPSG:6931',
  '+proj=laea +lat_0=90 +lon_0=0 +x_0=0 +y_0=0 +ellps=WGS84 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs'
);
register(proj4);
const projection = get('EPSG:6931');

const osm = new OSM();

const map = new Map({
  target: something,
  layers: [osm],
  view: new View({
    projection: projection,
    zoom: 5,
  }),
})

// Vector Styles
const unselectedStyle = new Style({
  stroke: new Stroke({
    color: 'rgba(50,50,50,0.9)',
    width: 1.2,
  }),
});
const selectedStyle = new Style({
  stroke: new Stroke({
    color: 'white',
    width: 2,
  }),
  fill: new Fill({
    color: 'rgba(0,0,0,0.3)',
  }),
});

const createVtLayer = () => {
  const vtSource = new VectorTileSource({
    tileGrid: new TileGrid({
      extent: [
        -9009964.761231285, -9009964.761231285, 9009964.761231285,
        9009964.761231285,
      ],
      tileSize: 256,
      resolutions: [70390.34969711941],
    }),
    projection: projection,
    format: new MVT({ idProperty: 'some_id' }),
    url:
      geoserverUrl +
      '/gwc/service/tms/1.0.0/' +
      mvtLayerName +
      '@EPSG%3A' +
      projection.getCode().split(':')[1] + // EPSG number of current projection
      '@pbf/{z}/{x}/{-y}.pbf',
  });

  return new VectorTileLayer({
    zIndex: 1,
    source: vtSource,
    style: unselectedStyle,
  });
};

const vtLayer = createVtLayer();

// Local lookup for highlighted features
let selection = null;
const selectionLayer = new VectorTileLayer({
  zIndex: 2,
  source: vtLayer.getSource(),
  style: feature => feature === selection && selectedStyle,
});

if (map && vtLayer && selectionLayer) {
  // Add layers to map once loaded into state
  map.addLayer(vtLayer);
  map.addLayer(selectionLayer);

  // Update styling of selectionLayer on mouse hover
  map.on(['pointermove', 'click'], event => {
    // Send vector metadata to parent component on mouse click
    if (event.type === 'click' && selection) {
      onFeatureSelect(selection);
    }
    map.forEachFeatureAtPixel(
      event.pixel,
      feature => {
        selection = feature;
      }, {
        layerFilter: layer => layer === vtLayer,
        hitTolerance: 1,
      }
    );
    selectionLayer.changed()
  });
}

到目前为止我已经尝试过什么

我试过调整 VectorTile 层中的renderBuffer 和renderMode 参数,以及调整map.forEachFeatureAtPixel 中的hitTolerance 选项,但我还没有运气。当我从 forEachFeatureAtPixel 中的特征参数记录特征 id 时,我注意到一些奇怪的事情——当发生意外行为时,将指针拖到相邻的边界线上后,选定的变量会在两个特征之间快速切换并分配不想要的一个,直到我将指针触摸到不相邻的边界线。修改hitTolerance 只会导致所选功能更频繁地切换。

理论和问题

我在想,也许我的相邻向量相互重叠?或者,向量作为 MVT 加载的方式可能存在问题?

【问题讨论】:

  • 功能可以跨图块边界分割。该示例依赖于它们具有在所有图块上都相同的 idProperty 此外,由于您有两个层 forEachFeatureAtPixel 将需要一个 layerFilter。
  • @Mike -- 感谢您的回复。我做了一些调整,但不幸的是问题仍然存在。如果这有助于澄清任何事情,我会添加一些有关将所选功能记录到控制台的信息。
  • 我认为这可能是因为您的 unselectedStyle 没有填充。未检测到未定义的填充,但您可以指定完全透明的填充以在多边形轮廓内进行命中检测。
  • @Mike 谢谢!这就像一个魅力!

标签: javascript openlayers geocoding openlayers-6 vector-tiles


【解决方案1】:

向 unselectedStyle 添加一个不可见的Fill() 可以检测到该图层并解决我的问题!

// Vector Styles
const unselectedStyle = new Style({
  stroke: new Stroke({
    color: 'rgba(50,50,50,0.9)',
    width: 1.2,
  }),
  fill: new Fill({
    color: 'rgba(0,0,0,0)',
  }),
});

谢谢迈克!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多