The map renders the features with the custom styles. Clicking on the map where the feature shows triggers the click event but the feature is not found. The feature is found if the map is clicked slightly below the displayed style. This also does not work every time. Some of the code is lifted from a project that uses OpenLayers 4.5.
I was following the guide to use OpenLayers with ReactJs provided here https://taylor.callsen.me/using-reactflux-with-openlayers-3-and-other-third-party-libraries/
I tried to use standard styles and those have the same problems. I also tried commenting out the 'projection: "EPSG:3857"' lines but this did not make any difference.
import React, { Component } from "react";
import * as ol from "ol";
import * as layer from "ol/layer";
import * as source from "ol/source";
import * as geom from "ol/geom";
import * as style from "ol/style";
import * as extent from "ol/extent";
import "ol/ol.css";
class MapWrapper extends Component {
constructor(props) {
super(props);
this.state = {
center: [-483760, 7480740],
zoom: 8,
rotation: 0,
circleRadius: 10,
circleBorder: 1,
circleBorderColor: "#212121"
};
}
componentDidMount() {
let featureSource = new source.Vector({
projection: "EPSG:3857",
features: this.getFeatures()
});
let clusterSource = new source.Cluster({
distance: 16,
projection: "EPSG:3857",
source: featureSource
});
let clusterLayer = new layer.Vector({
projection: "EPSG:3857",
source: clusterSource,
style: cluster => this.getClusterStyle(cluster)
});
let map = new ol.Map({
target: this.refs.mapContainer,
layers: [
new layer.Tile({
projection: "EPSG:3857",
source: new source.OSM()
}),
clusterLayer
],
view: new ol.View({
projection: "EPSG:3857",
center: this.state.center,
zoom: this.state.zoom,
rotation: this.state.rotation
})
});
this.setState({
map: map,
clusterSource: clusterSource
});
map.on("click", this.handleMapClick.bind(this));
}
componentDidUpdate(prevProps, prevState) {
if (prevProps.data.length !== this.props.data.length) {
let featureSource = this.state.clusterSource.getSource();
featureSource.clear();
featureSource.addFeatures(this.getFeatures());
}
}
getFeatures() {
let features = [];
// let data = [{"id":1,"x":-483760,"y":7480740},{"id":2,"x":-483760,"y":7480840}]
this.props.data.forEach(element => {
let feature = new ol.Feature({
geometry: new geom.Point([element.x, element.y]),
attributes: { ...element }
});
feature.setStyle([
new style.Style({
image: new style.Circle({
radius: this.state.circleRadius,
stroke: new style.Stroke({
color: this.state.circleBorderColor,
width: this.state.circleBorder
}),
fill: new style.Fill({
color: "#fff"
})
})
}),
new style.Style({
rotateWithView: true,
textAlign: "center",
text: new style.Text({
text: "?"
})
})
]);
features.push(feature);
});
return features;
}
getClusterStyle(cluster) {
let clusterSize = cluster.get("features").length;
if (clusterSize > 1) {
return new style.Style({
image: new style.Circle({
radius: this.state.circleRadius,
stroke: new style.Stroke({
color: this.state.circleBorderColor,
width: this.state.circleBorder
}),
fill: new style.Fill({
color: "#ff9900"
})
}),
text: new style.Text({
text: clusterSize.toString(),
fill: new style.Fill({
color: this.state.circleBorderColor
})
})
});
} else {
return cluster.get("features")[0].getStyle();
}
}
handleMapClick(event) {
this.state.map.forEachFeatureAtPixel(event.pixel, (cluster, layer) => {
let markers = cluster.get("features");
if (markers.length == 1) {
setTimeout(() => {
console.log(markers[0].getProperties().attributes));
}, 300);
} else {
var extentObj = extent.createEmpty();
markers.forEach(marker => {
extent.extend(extentObj, marker.getGeometry().getExtent());
});
this.state.map.getView().fit(extentObj, this.state.map.getSize());
this.state.map.getView().setZoom(this.state.map.getView().getZoom() - 1);
}
});
}
render() {
return <div ref="mapContainer" style={{ height: "100%" }} />;
}
}
export default MapWrapper;
The expected result is to find the feature by clicking on its displayed style.