如何在openlayers 3中的图标周围添加可点击边距?

时间:2016-06-15 11:15:01

标签: javascript touch openlayers-3

我正在使用openlayers 3来显示带有一些带有小图标的标记的地图。单击其中一个后,浏览器将切换到与标记关联的另一个页面。

标记目前已作为功能实现:

const style = new ol.style.Style({
    image: new ol.style.Icon({
        anchor: [0.5, 1.0],
        anchorXUnits: 'fraction',
        anchorYUnits: 'fraction',
        src: img_url,
    })
});

const feature = new ol.Feature({
    geometry: new ol.geom.Point([x, y]),
});

feature.setStyle(style);

这是我的点击处理程序:

map.on("click", e => {
    map.forEachFeatureAtPixel(e.pixel, (feature) => {
        window.location.href = "/s/" + feature.getId();
        return true; // stop after first feature
    });
});

不幸的是,这些图标非常小,因此难以在基于触摸的界面(例如iPad)上点击。

是否有可接受的方法使目标更大?我的想法如下:

  • 为每个标记创建一个额外的不可见标记,并使其可单击。
  • 我可以对周围的一些像素进行采样并使用附近的所有功能,而不是仅使用事件的位置。

有更好的方法吗?

2 个答案:

答案 0 :(得分:1)

我的建议是你在图标周围创建一个隐形方块,如:

const style = [
  new ol.style.Style({
    image: new ol.style.Icon({
      anchor: [0.5, 1.0],
      anchorXUnits: 'fraction',
      anchorYUnits: 'fraction',
      src: img_url,
    })
  }),
  new ol.style.Style({
    image: new ol.style.RegularShape({
      stroke: new ol.style.Stroke({ color: [0, 0, 0, 0] }),
      points: 4,
      radius: 50, // <--------- control its size
      angle: Math.PI / 4
    })
  })
];

答案 1 :(得分:1)

我最初尝试过Jonatas的方法,我添加了更大的风格。这非常有效。需要注意的是,在点击某个要素时,我们必须找出哪个要素最接近,因为它们很容易重叠。

在发现getClosestFeatureToCoordinate()方法后,我终于决定采用稍微不同的方法。我在click处理程序中执行所有操作:

map.on("click", event => {
    const distance = feature => {
        const coords = feature.getGeometry().getCoordinates();
        const pixel = map.getPixelFromCoordinate(coords);
        const distSquared = Math.pow(event.pixel[0] - pixel[0], 2)
                          + Math.pow(event.pixel[1] - pixel[1], 2);
        return distSquared;
    };

    const clickedFeature = { feat: null, dist: Infinity };

    /* See if we clicked on a feature. If yes, take closest */
    map.forEachFeatureAtPixel(event.pixel, (feature) => {
        const dist = distance(feature);
        if (dist < clickedFeature.dist) {
            clickedFeature.feat = feature;
            clickedFeature.dist = dist;
        }
    });

    /* If we are touch-based, we also take into account clicks that happen nearby */
    if (!clickedFeature.feat) {
        if (ol.has.TOUCH) {
            const coords = this._map.getCoordinateFromPixel(event.pixel);
            const closestFeat = this._featureSource.getClosestFeatureToCoordinate(coords);

            const dist = distance(closestFeat);
            /* touch size taken from Apple's guidelines */
            if (dist < Math.pow(22,2)) {
                clickedFeature.feat = closestFeat;
                clickedFeature.dist = dist;
            }
        }
    }

    /* go to station */
    if (clickedFeature.feat) {
        window.location.href = "/s/" + clickedFeature.feat.getId();
    }
});