[英]How to refresh/re-render an OpenLayers 6 Map
我有一个 React 组件,我在其中渲染了 Open Layers 6 map。 我将纬度/经度坐标作为道具 (props.userEnteredLocation) 传递给 map,它被转换为开放层期望的格式,以便能够呈现正确的位置。
我的State如下:
const transformCentre = (centre) => {
return transform(centre, "EPSG:4326", "EPSG:3857");
};
const [map, setMap] = useState();
const [centre, setCentre] = useState([74.31071359697442, 31.588167443954312]);
const [featuresLayer, setFeaturesLayer] = useState();
const [point, setPoint] = useState();
const [feature, setFeature] = useState();
const [transformedCentre, setTransformedCentre] = useState(
transformCentre(centre)
);
// create state ref that can be accessed in OpenLayers onclick callback function
// https://stackoverflow.com/a/60643670
const mapRef = useRef();
mapRef.current = map;
我有两个 React 钩子
// initialize map on first render - logic formerly put into componentDidMount
useEffect(() => {
console.log("Initialised for the first time");
// Create a point
var point = new Point(transformedCentre);
setPoint(point);
// points/lines/polygons are features that can be used in the vector layer
var feature = new Feature({
geometry: point,
name: "Your address is shown here",
});
var iconStyle = new Style({
image: new Icon({
src: markerImg,
}),
});
feature.setStyle(iconStyle);
setFeature(feature);
// create vector source itself for the marker on the map
var vectorSource = new VectorSource({
features: [feature],
});
// create and add vector source layer
const initalFeaturesLayer = new VectorLayer({
source: vectorSource,
});
// create map
const locationMap = new Map({
target: mapRef.current,
layers: [
new TileLayer({
source: new OSM(),
}),
initalFeaturesLayer,
],
view: new View({
center: transformedCentre,
zoom: 17,
}),
controls: [],
});
setMap(locationMap);
setFeaturesLayer(initalFeaturesLayer);
}, []);
// update map if user changes geo location
useEffect(() => {
console.log("Detected change in User geolocation");
if (props.userEnteredLocation) {
var array = props.userEnteredLocation.split(",");
var newCentre = [parseFloat(array[1]), parseFloat(array[0])];
setCentre(newCentre);
setTransformedCentre(transformCentre(centre));
}
if (map != null) {
console.log("Changing Centre to: " + transformedCentre);
map.getView().setCenter(transformedCentre);
console.log("CENTRE NOW: " + map.getView().getCenter());
point.setCoordinates(transformedCentre);
console.log("POINT CENTRE NOW: " + point.getCoordinates());
feature.setGeometry(point);
console.log("Feature geometry now CENTRE NOW: " + feature.getGeometry());
// set features to map
featuresLayer.setSource(
new VectorSource({
features: [feature],
})
);
featuresLayer.getSource().changed();
}
}, [props.userEnteredLocation]);
//render component
return <div ref={mapRef} className="map-container"></div>;
我已经按照常见问题解答的建议尝试了 map.render() 和 map.renderSync() 无济于事。 我还在 VectorSource 本身上尝试了 .changed() 和 .refresh() , .changed() 什么也不做, .refresh() 完全删除了我的红色标记。
有谁知道我要去哪里错了? 我希望 map 重新渲染并显示来自道具的新位置,并在该位置显示红色 map 标记。
我很想创建一个新的 map,即将我在初始渲染中所做的一切粘贴到随着道具变化而变化的钩子中,但这似乎不是最佳的。
对于这可能会有所帮助的任何人,我意识到问题实际上只是 useEffect() 在组件的下一次渲染之前没有使用更新的 state。 为了让它使用最新的坐标,我将 map 所需的中心分配给一个 var,然后再将其传递给 Openlayers 视图和布局。
这是有效的代码:
function BusinessLocationMap(props) {
// Transform the centre into something openlayers understands
const transformCentre = (centre) => {
if (centre != null) {
return transform(centre, "EPSG:4326", "EPSG:3857");
}
};
const [map, setMap] = useState();
const [centre] = useState([74.31071359697442, 31.588167443954312]);
const [featuresLayer, setFeaturesLayer] = useState();
const [point, setPoint] = useState();
const [feature, setFeature] = useState();
const [transformedCentre] = useState(transformCentre(centre));
// create state ref that can be accessed in OpenLayers onclick callback function
// https://stackoverflow.com/a/60643670
const mapRef = useRef();
mapRef.current = map;
// initialize map on first render - logic formerly put into componentDidMount
useEffect(() => {
console.log("Initialised for the first time");
console.log("Initial Centre used: " + transformedCentre);
// Create a point
var point = new Point(transformedCentre);
setPoint(point);
// points/lines/polygons are features that can be used in the vector layer
var feature = new Feature({
geometry: point,
name: "Your address is shown here",
});
var iconStyle = new Style({
image: new Icon({
src: markerImg,
}),
});
feature.setStyle(iconStyle);
setFeature(feature);
// create vector source itself for the marker on the map
var vectorSource = new VectorSource({
features: [feature],
});
// create and add vector source layer
const initalFeaturesLayer = new VectorLayer({
source: vectorSource,
});
// create the initial view
const initialView = new View({
center: transformedCentre,
zoom: 17,
});
// create map
const locationMap = new Map({
target: mapRef.current,
layers: [
new TileLayer({
source: new OSM(),
}),
initalFeaturesLayer,
],
view: initialView,
controls: [],
});
setMap(locationMap);
setFeaturesLayer(initalFeaturesLayer);
}, []);
// update map if user changes geo location
useEffect(() => {
console.log("Detected change in User geolocation");
if (props.userEnteredLocation) {
var array = props.userEnteredLocation.split(",");
var newCentre = [parseFloat(array[1]), parseFloat(array[0])];
var newTransformedCentre = transformCentre(newCentre);
}
if (map != null) {
point.setCoordinates(newTransformedCentre);
feature.setGeometry(point);
map.setView(
new View({
center: newTransformedCentre,
zoom: 17,
})
);
// set features to map
featuresLayer.setSource(
new VectorSource({
features: [feature],
})
);
}
}, [props.userEnteredLocation]);
//render component
return <div ref={mapRef} className="map-container"></div>;
}
export default BusinessLocationMap;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.