OpenLayers 对 MVT 层悬停选择的不一致命中检测
OpenLayers Inconsistent Hit Detection on MVT Layer Hover Selection
objective
我正在尝试从 OpenLayers 站点复制 this example 中的“单选悬停”功能。
问题
当我尝试使用此实现时,vtLayer.getFeatures(event.pixel)
的命中检测非常差。 documentation for the function 状态:
The hit detection algorithm used for this method is optimized for performance, but is less accurate than the one used in 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 加载的方式可能存在问题?
向 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)',
}),
});
谢谢迈克!
objective
我正在尝试从 OpenLayers 站点复制 this example 中的“单选悬停”功能。
问题
当我尝试使用此实现时,vtLayer.getFeatures(event.pixel)
的命中检测非常差。 documentation for the function 状态:
The hit detection algorithm used for this method is optimized for performance, but is less accurate than the one used in 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 加载的方式可能存在问题?
向 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)',
}),
});
谢谢迈克!