在 OpenLayers 中的节点上悬停时添加工具提示

问题描述 投票:0回答:2

我有一个 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 删除工作的范围内)

javascript gis openlayers
2个回答
0
投票

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);
    }
  }
})


0
投票

采纳 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);
});

完整代码和盒子示例

© www.soinside.com 2019 - 2024. All rights reserved.