我正在使用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)上击中。
是否有一种使目标更大的公认方法?我的想法如下:
- 为每个标记创建一个额外的不可见标记,并使这些标记可单击。
- 我不仅可以使用事件的位置,还可以在其周围采样一些像素并使用附近的所有功能。
有更好的方法吗?
我的建议是您在图标周围创建一个隐形的正方形,例如:
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
})
})
];
我最初尝试了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();
}
});