OpenLayers:如何阻止点击导致不应该选择的选择?



要复制,请单击包含文本4的蓝色标记。因为这是一个聚类标记,它所聚类的所有标记都在同一个坐标上,所以试图放大是没有意义的。我没有放大,而是把地图放在标记的中心。

但是,点击4标记会导致点击左边的大矩形,从而触发矩形的Select操作。这当然不应该发生。

如果我正在进行居中操作,我已经尝试告诉事件不要传播,但这没有帮助。

我需要改变什么,以使选择不被触发?

function createRectangle(polygons, layerName) {
const features = [];
for (const [i, polygon] of polygons.entries()) {
const feature = {
type: "Feature",
geometry: {
type: "Polygon",
coordinates: polygon
},
properties: {
id: `${layerName} index ${i}`,
layerName
}
};
features.push(feature);
}
const json = {
type: "FeatureCollection",
features
};
return json;
}
function createPoints(points, groupName) {
const features = [];
for (const [i, point] of points.entries()) {
const feature = {
type: "Feature",
geometry: {
type: "Point",
coordinates: point
},
properties: {
id: `${groupName} index ${i}`,
groupName
}
};
features.push(feature);
}
const json = {
type: "FeatureCollection",
features
};
return json;
}
const thePoints = createPoints(
[
[50, 33],
[50, 33],
[50, 33],
[50, 33]
],
"thePoints"
);
const styles = {
Point: new ol.style.Style({
image: new ol.style.Circle({
radius: 7,
fill: new ol.style.Fill({ color: "red" })
}),
stroke: new ol.style.Stroke({
color: "hsla(0, 50%, 100%, 1.0)",
width: 5
}),
fill: new ol.style.Fill({
color: "hsla(0, 50%, 50%, 1.0)"
})
}),
Polygon: new ol.style.Style({
stroke: new ol.style.Stroke({
color: "hsla(0, 50%, 100%, 1.0)",
width: 5
}),
fill: new ol.style.Fill({
color: "hsla(0, 50%, 50%, 1.0)"
})
})
};
const styleFunction = function (feature) {
const featureType = feature.getGeometry().getType();
return styles[featureType];
};
const vectorSource = new ol.source.Vector({
features: new ol.format.GeoJSON({
featureProjection: "EPSG:4326" // 4326 3857
}).readFeatures(thePoints)
});
const cluster = new ol.source.Cluster({
distance: 30,
minDistance: 10,
source: vectorSource
});
const styleCache = {};
const vectorLayer = new ol.layer.Vector({
source: cluster,
style: function (feature) {
const size = feature.get("features").length;
let style = styleCache[size];
if (!style) {
style = new ol.style.Style({
image: new ol.style.Circle({
radius: 10,
stroke: new ol.style.Stroke({
color: "#fff"
}),
fill: new ol.style.Fill({
color: "#3399CC"
})
}),
text: new ol.style.Text({
text: size.toString(),
fill: new ol.style.Fill({
color: "#fff"
})
})
});
styleCache[size] = style;
}
return style;
},
zIndex: 5,
properties: {
name: "big"
}
});
const rectangles = createRectangle(
[
[
[
[-120, -75],
[-120, 75],
[45, 75],
[45, -75]
]
]
],
"rectangle"
);
const rectangleSource = new ol.source.Vector({
features: new ol.format.GeoJSON({
featureProjection: "EPSG:4326" // 4326 3857
}).readFeatures(rectangles)
});
const rectangleLayer = new ol.layer.Vector({
source: rectangleSource,
style: styleFunction,
zIndex: 5
});
const map = new ol.Map({
target: "map",
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
}),
vectorLayer,
rectangleLayer
],
view: new ol.View({
projection: "EPSG:4326",
center: [179, 0],
zoom: 1
})
});
map.on("click", (e) => {
vectorLayer.getFeatures(e.pixel).then((clickedFeatures) => {
if (clickedFeatures.length) {
// Get clustered Coordinates
const features = clickedFeatures[0].get("features");
if (features.length > 1) {
e.stopPropagation();
const extent = ol.extent.boundingExtent(
features.map((r) => r.getGeometry().getCoordinates())
);
const extentSize = ol.extent.getSize(extent);
const isSmallExtent = extentSize[0] === 0 && extentSize[1] === 0;
console.log("isSmallExtent", isSmallExtent);
if (isSmallExtent) {
const viewport = map.getViewport();
const boundingRect = viewport.getBoundingClientRect();
console.log("boundingRect", boundingRect);
const centerPoint = [
(boundingRect.left + boundingRect.right) / 2,
(boundingRect.top + boundingRect.bottom) / 2
];
console.log("centerPoint", centerPoint);
map
.getView()
.centerOn(ol.extent.getCenter(extent), map.getSize(), centerPoint);
} else {
map
.getView()
.fit(extent, { duration: 1000, padding: [50, 50, 50, 50] });
}
}
}
});
});
const selected = new ol.style.Style({
fill: new ol.style.Fill({
color: "hsla(270, 50%, 50%, .1)"
}),
stroke: new ol.style.Stroke({
color: "hsla(270, 50%, 50%, 1)",
width: 5
})
});
const selectSingleClick = new ol.interaction.Select({
style: (feature) => {
const color = "hsla(270, 50%, 50%, .1)";
selected.getFill().setColor(color);
return selected;
},
layers: [rectangleLayer],
condition: function (e) {
return (
ol.events.condition.singleClick(e) &&
map.getFeaturesAtPixel(e.pixel, {
layerFilter: function (l) {
return l.getZIndex() > vectorLayer.getZIndex();
}
}).length === 0
);
}
});
selectSingleClick.on("select", function (e) {
console.log("selectSingleClick onSelect");
});
map.addInteraction(selectSingleClick);
#map {
height: 512px;
width: 1024px;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/openlayers/7.3.0/ol.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/openlayers/7.3.0/dist/ol.min.js"></script>
<div id="map"></div>

您可以简单地在单次单击期间停用选择交互作用(单击后触发500毫秒,以确保它不是双击)

selectSingleClick.setActive(false);
setTimeout(() => { selectSingleClick.setActive(true); }, 600);

function createRectangle(polygons, layerName) {
const features = [];
for (const [i, polygon] of polygons.entries()) {
const feature = {
type: "Feature",
geometry: {
type: "Polygon",
coordinates: polygon
},
properties: {
id: `${layerName} index ${i}`,
layerName
}
};
features.push(feature);
}
const json = {
type: "FeatureCollection",
features
};
return json;
}
function createPoints(points, groupName) {
const features = [];
for (const [i, point] of points.entries()) {
const feature = {
type: "Feature",
geometry: {
type: "Point",
coordinates: point
},
properties: {
id: `${groupName} index ${i}`,
groupName
}
};
features.push(feature);
}
const json = {
type: "FeatureCollection",
features
};
return json;
}
const thePoints = createPoints(
[
[50, 33],
[50, 33],
[50, 33],
[50, 33]
],
"thePoints"
);
const styles = {
Point: new ol.style.Style({
image: new ol.style.Circle({
radius: 7,
fill: new ol.style.Fill({ color: "red" })
}),
stroke: new ol.style.Stroke({
color: "hsla(0, 50%, 100%, 1.0)",
width: 5
}),
fill: new ol.style.Fill({
color: "hsla(0, 50%, 50%, 1.0)"
})
}),
Polygon: new ol.style.Style({
stroke: new ol.style.Stroke({
color: "hsla(0, 50%, 100%, 1.0)",
width: 5
}),
fill: new ol.style.Fill({
color: "hsla(0, 50%, 50%, 1.0)"
})
})
};
const styleFunction = function (feature) {
const featureType = feature.getGeometry().getType();
return styles[featureType];
};
const vectorSource = new ol.source.Vector({
features: new ol.format.GeoJSON({
featureProjection: "EPSG:4326" // 4326 3857
}).readFeatures(thePoints)
});
const cluster = new ol.source.Cluster({
distance: 30,
minDistance: 10,
source: vectorSource
});
const styleCache = {};
const vectorLayer = new ol.layer.Vector({
source: cluster,
style: function (feature) {
const size = feature.get("features").length;
let style = styleCache[size];
if (!style) {
style = new ol.style.Style({
image: new ol.style.Circle({
radius: 10,
stroke: new ol.style.Stroke({
color: "#fff"
}),
fill: new ol.style.Fill({
color: "#3399CC"
})
}),
text: new ol.style.Text({
text: size.toString(),
fill: new ol.style.Fill({
color: "#fff"
})
})
});
styleCache[size] = style;
}
return style;
},
zIndex: 5,
properties: {
name: "big"
}
});
const rectangles = createRectangle(
[
[
[
[-120, -75],
[-120, 75],
[45, 75],
[45, -75]
]
]
],
"rectangle"
);
const rectangleSource = new ol.source.Vector({
features: new ol.format.GeoJSON({
featureProjection: "EPSG:4326" // 4326 3857
}).readFeatures(rectangles)
});
const rectangleLayer = new ol.layer.Vector({
source: rectangleSource,
style: styleFunction,
zIndex: 5
});
const map = new ol.Map({
target: "map",
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
}),
vectorLayer,
rectangleLayer
],
view: new ol.View({
projection: "EPSG:4326",
center: [179, 0],
zoom: 1
})
});
let selectSingleClick;
map.on("click", (e) => {
vectorLayer.getFeatures(e.pixel).then((clickedFeatures) => {
if (clickedFeatures.length) {
// Get clustered Coordinates
const features = clickedFeatures[0].get("features");
if (features.length > 1) {
selectSingleClick.setActive(false);
setTimeout(() => { selectSingleClick.setActive(true); }, 600);
const extent = ol.extent.boundingExtent(
features.map((r) => r.getGeometry().getCoordinates())
);
const extentSize = ol.extent.getSize(extent);
const isSmallExtent = extentSize[0] === 0 && extentSize[1] === 0;
console.log("isSmallExtent", isSmallExtent);
if (isSmallExtent) {
const viewport = map.getViewport();
const boundingRect = viewport.getBoundingClientRect();
console.log("boundingRect", boundingRect);
const centerPoint = [
(boundingRect.left + boundingRect.right) / 2,
(boundingRect.top + boundingRect.bottom) / 2
];
console.log("centerPoint", centerPoint);
map
.getView()
.centerOn(ol.extent.getCenter(extent), map.getSize(), centerPoint);
} else {
map
.getView()
.fit(extent, { duration: 1000, padding: [50, 50, 50, 50] });
}
}
}
});
});
const selected = new ol.style.Style({
fill: new ol.style.Fill({
color: "hsla(270, 50%, 50%, .1)"
}),
stroke: new ol.style.Stroke({
color: "hsla(270, 50%, 50%, 1)",
width: 5
})
});
selectSingleClick = new ol.interaction.Select({
style: (feature) => {
const color = "hsla(270, 50%, 50%, .1)";
selected.getFill().setColor(color);
return selected;
},
layers: [rectangleLayer],
condition: function (e) {
return (
ol.events.condition.singleClick(e) &&
map.getFeaturesAtPixel(e.pixel, {
layerFilter: function (l) {
return l.getZIndex() > vectorLayer.getZIndex();
}
}).length === 0
);
}
});
selectSingleClick.on("select", function (e) {
console.log("selectSingleClick onSelect");
});
map.addInteraction(selectSingleClick);
#map {
height: 512px;
width: 1024px;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/openlayers/7.3.0/ol.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/openlayers/7.3.0/dist/ol.min.js"></script>
<div id="map"></div>

只有当映射click引起某种动作,并且在选择条件下测试其值时,才可以使用clickHandled布尔集来避免使用setTimeout:

function createRectangle(polygons, layerName) {
const features = [];
for (const [i, polygon] of polygons.entries()) {
const feature = {
type: "Feature",
geometry: {
type: "Polygon",
coordinates: polygon
},
properties: {
id: `${layerName} index ${i}`,
layerName
}
};
features.push(feature);
}
const json = {
type: "FeatureCollection",
features
};
return json;
}
function createPoints(points, groupName) {
const features = [];
for (const [i, point] of points.entries()) {
const feature = {
type: "Feature",
geometry: {
type: "Point",
coordinates: point
},
properties: {
id: `${groupName} index ${i}`,
groupName
}
};
features.push(feature);
}
const json = {
type: "FeatureCollection",
features
};
return json;
}
const thePoints = createPoints(
[
[50, 33],
[50, 33],
[50, 33],
[50, 33]
],
"thePoints"
);
const styles = {
Point: new ol.style.Style({
image: new ol.style.Circle({
radius: 7,
fill: new ol.style.Fill({ color: "red" })
}),
stroke: new ol.style.Stroke({
color: "hsla(0, 50%, 100%, 1.0)",
width: 5
}),
fill: new ol.style.Fill({
color: "hsla(0, 50%, 50%, 1.0)"
})
}),
Polygon: new ol.style.Style({
stroke: new ol.style.Stroke({
color: "hsla(0, 50%, 100%, 1.0)",
width: 5
}),
fill: new ol.style.Fill({
color: "hsla(0, 50%, 50%, 1.0)"
})
})
};
const styleFunction = function (feature) {
const featureType = feature.getGeometry().getType();
return styles[featureType];
};
const vectorSource = new ol.source.Vector({
features: new ol.format.GeoJSON({
featureProjection: "EPSG:4326" // 4326 3857
}).readFeatures(thePoints)
});
const cluster = new ol.source.Cluster({
distance: 30,
minDistance: 10,
source: vectorSource
});
const styleCache = {};
const vectorLayer = new ol.layer.Vector({
source: cluster,
style: function (feature) {
const size = feature.get("features").length;
let style = styleCache[size];
if (!style) {
style = new ol.style.Style({
image: new ol.style.Circle({
radius: 10,
stroke: new ol.style.Stroke({
color: "#fff"
}),
fill: new ol.style.Fill({
color: "#3399CC"
})
}),
text: new ol.style.Text({
text: size.toString(),
fill: new ol.style.Fill({
color: "#fff"
})
})
});
styleCache[size] = style;
}
return style;
},
zIndex: 5,
properties: {
name: "big"
}
});
const rectangles = createRectangle(
[
[
[
[-120, -75],
[-120, 75],
[45, 75],
[45, -75]
]
]
],
"rectangle"
);
const rectangleSource = new ol.source.Vector({
features: new ol.format.GeoJSON({
featureProjection: "EPSG:4326" // 4326 3857
}).readFeatures(rectangles)
});
const rectangleLayer = new ol.layer.Vector({
source: rectangleSource,
style: styleFunction,
zIndex: 5
});
const map = new ol.Map({
target: "map",
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
}),
vectorLayer,
rectangleLayer
],
view: new ol.View({
projection: "EPSG:4326",
center: [179, 0],
zoom: 1
})
});
let clickHandled = false;
map.on("click", (e) => {
vectorLayer.getFeatures(e.pixel).then((clickedFeatures) => {
clickHandled = false;
if (clickedFeatures.length) {
// Get clustered Coordinates
const features = clickedFeatures[0].get("features");
if (features.length > 1) {
clickHandled = true;
const extent = ol.extent.boundingExtent(
features.map((r) => r.getGeometry().getCoordinates())
);
const extentSize = ol.extent.getSize(extent);
const isSmallExtent = extentSize[0] === 0 && extentSize[1] === 0;
console.log("isSmallExtent", isSmallExtent);
if (isSmallExtent) {
const viewport = map.getViewport();
const boundingRect = viewport.getBoundingClientRect();
console.log("boundingRect", boundingRect);
const centerPoint = [
(boundingRect.left + boundingRect.right) / 2,
(boundingRect.top + boundingRect.bottom) / 2
];
console.log("centerPoint", centerPoint);
map
.getView()
.centerOn(ol.extent.getCenter(extent), map.getSize(), centerPoint);
} else {
map
.getView()
.fit(extent, { duration: 1000, padding: [50, 50, 50, 50] });
}
}
}
});
});
const selected = new ol.style.Style({
fill: new ol.style.Fill({
color: "hsla(270, 50%, 50%, .1)"
}),
stroke: new ol.style.Stroke({
color: "hsla(270, 50%, 50%, 1)",
width: 5
})
});
selectSingleClick = new ol.interaction.Select({
style: (feature) => {
const color = "hsla(270, 50%, 50%, .1)";
selected.getFill().setColor(color);
return selected;
},
layers: [rectangleLayer],
condition: function (e) {
return (
!clickHandled &&
ol.events.condition.singleClick(e) &&
map.getFeaturesAtPixel(e.pixel, {
layerFilter: function (l) {
return l.getZIndex() > vectorLayer.getZIndex();
}
}).length === 0
);
}
});
selectSingleClick.on("select", function (e) {
console.log("selectSingleClick onSelect");
});
map.addInteraction(selectSingleClick);
#map {
height: 512px;
width: 1024px;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/openlayers/7.3.0/ol.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/openlayers/7.3.0/dist/ol.min.js"></script>
<div id="map"></div>

相关内容

  • 没有找到相关文章

最新更新