我有一个 OpenLayers 地图,人们可以在上面绘制和修改几何图形。对于多边形和线串,您可以通过按住 alt 并单击节点来删除各个节点,但如果没有进一步说明,这对用户来说并不明显。
我希望能够在用户将鼠标悬停在节点上时添加工具提示,告诉他们可以执行此操作,但我无法弄清楚执行此操作的确切步骤。
采用以下代码,根据绘制和修改和自定义多边形样式示例进行修改(下面的工作代码沙箱)
const raster = new TileLayer({
source: new OSM()
});
const source = new VectorSource();
const vector = new VectorLayer({
source: source,
style: [
new Style({
fill: new Fill({
color: "rgba(255, 255, 255, 0.2)"
}),
stroke: new Stroke({
color: "#ffcc33",
width: 2
}),
image: new CircleStyle({
radius: 7,
fill: new Fill({
color: "#ffcc33"
})
})
}),
new Style({
image: new CircleStyle({
radius: 5,
fill: new Fill({
color: "orange"
})
}),
geometry: function (feature) {
// return the coordinates of the first ring of the polygon
const coordinates = feature.getGeometry().getCoordinates()[0];
return new MultiPoint(coordinates);
}
})
]
});
// Limit multi-world panning to one world east and west of the real world.
// Geometry coordinates have to be within that range.
const map = new Map({
layers: [raster, vector],
target: "map",
view: new View({
center: [-11000000, 4600000],
zoom: 4
})
});
const modify = new Modify({
source: source
});
map.addInteraction(modify);
let draw, snap; // global so we can remove them later
const typeSelect = document.getElementById("type");
function addInteractions() {
draw = new Draw({
source: source,
type: typeSelect.value
});
map.addInteraction(draw);
// snap = new Snap({ source: source });
// map.addInteraction(snap);
}
addInteractions();
https://codesandbox.io/s/draw-and-modify-features-forked-cl85wd?file=/main.js:1860-1975
这使用自定义多边形样式来显示节点,我想要的是,当您将鼠标悬停在节点上时,它会在旁边出现一个小工具提示,告诉用户如何删除节点。
我觉得这可以通过两种方式之一来完成,但我都陷入了特定的部分。
选项 1:将其添加到样式中。您可以将“文本”添加到用于渲染节点的样式中,但这将始终适用,并且我看不到仅在悬停单个节点时才应用它的方法。
选项 2:添加“pointerMove”事件并检测您何时将鼠标悬停在节点上,然后在鼠标旁边显示工具提示(非常类似于 measure example 在鼠标旁边显示工具提示)。我可以检测到某个功能何时悬停在某个节点上,但无法检测到用户是否将鼠标悬停在某个节点上(并且处于 Alt Click 删除工作的范围内)
var tooltip = document.getElementById('tooltip');
var tooltipOverlay = new ol.Overlay({
element: tooltip,
offset: [10, 0],
positioning: 'bottom-left'
});
map.addOverlay(tooltipOverlay);
map.on('pointermove',function(e){
if( source.getFeatures().length ){
let v = false;
source.getFeatures().forEach(f=>{
if( f.getGeometry().getType() !== 'Point' ){
let coords = f.getGeometry().getType() == 'LineString'?f.getGeometry().getCoordinates():f.getGeometry().getLinearRing().getCoordinates();
coords.forEach(c=>{
let p2 = map.getPixelFromCoordinate(c);
var dx = e.pixel[0] - p2[0];
var dy = e.pixel[1] - p2[1];
if( (Math.sqrt(dx*dx + dy*dy)) < 8 ){
v = true;
}
})
}
})
if( v ){
tooltip.style.display = '';
tooltip.innerHTML = 'Alt+click - delete vertex!';
tooltipOverlay.setPosition(e.coordinate);
}else{
tooltip.style.display = 'none';
tooltip.innerHTML = '';
tooltipOverlay.setPosition(undefined);
}
}
})
采纳 Mikes 在评论中的建议,我最终得到了一个解决方案,其中帮助文本会出现在节点悬停时,并且只有多边形中的坐标超过 3 个(少于 3 个坐标,您就无法删除节点,因为它将不再是一个有效的多边形。
相关代码在这里
modify.getOverlay().setStyle(function (feature) {
const coordinate = feature.getGeometry().getCoordinates();
let style = defaultEditingStyleFunction;
map.forEachFeatureAtPixel(map.getPixelFromCoordinate(coordinate), function (
feature
) {
const geometry = feature.getGeometry();
if (geometry.getType() === "Polygon") {
const coordinates = geometry
.getCoordinates()[0]
.map(function (coordinate) {
return coordinate.toString();
});
if (
coordinates.length > 4 &&
coordinates.includes(coordinate.toString())
) {
style = function () {
return vertexStyle;
};
return true;
}
}
});
return style(feature);
});