【发布时间】: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