Open layers add new feature
День добрый. По двойному клику появляется формочка с двумя полями и кнопкой. Вводится заголовок и описание, по нажатию на кнопку сохраняется, и выводится в панельке справа вверху, но вновь созданная точка на карте не отрисовывается. Подскажите люди добрые как заставить карту перерисоватся.
import {Map, View, Collection} from "ol";
import TileLayer from "ol/layer/Tile";
import OSM from "ol/source/OSM";
import Vector from "ol/layer/Vector";
import SourceVector from "ol/source/Vector";
import Point from "ol/geom/Point";
import {MousePosition, ScaleLine} from "ol/control";
import Overlay from "ol/Overlay";
import VectorLayer from "ol/layer/Vector";
import VectorSource from "ol/source/Vector";
import {LineString, Polygon} from "ol/geom";
import {getArea, getLength} from "ol/sphere";
import {Circle as CircleStyle, Fill, Stroke, Style, Icon, Circle} from "ol/style";
import Draw from "ol/interaction/Draw";
import {unByKey} from "ol/Observable";
import Feature from "ol/Feature";
import Select from "ol/interaction/Select";
export default function Mapps(props) {
const basePointList = [
{
id: 1,
title: "title1",
description: "description1",
coordinates: [4420473.128288177, 5981906.298371299]
},
{
id: 2,
title: "title2",
description: "description2",
coordinates: [4420290.396017432, 5981647.129072269]
},
{
id: 3,
title: "title3",
description: "description3",
coordinates: [4420702.439373032, 5981968.403456781]
}
];
const [renderModal, setRenderModal] = useState({render: false, coordinate: []});
const [renderMeasure, setRenderMeasure] = useState(false);
const [title, setTitle] = useState("");
const [description, setDescription] = useState("");
const [coordinates, setCoordinates] = useState("");
const [markers, setMarkers] = useState([]);
const [pointList, setPointList] = useState(basePointList);
const [features, setFeatures] = useState([]);
const [renderPointInfo, setRenderPointInfo] = useState({show: false, feature: {}});
useEffect(() => {
const container = document.getElementById("popup");
const overlay = new Overlay({
element: container,
autoPan: true,
autoPanAnimation: {
duration: 250
}
});
const map = new Map({
target: "map",
views: new VectorLayer({}),
layers: [
//@ts-ignore
new TileLayer({
//@ts-ignore
source: new OSM()
})
],
overlays: [overlay]
});
//вызов модалки добавления точки
map.on("dblclick", function (evt) {
const coordinate = evt.coordinate;
setRenderModal({render: true, coordinate: coordinate});
setCoordinates(coordinate);
overlay.setPosition(coordinate);
});
pointList.map((element) => {
features.push(
//@ts-ignore
new Feature({
// @ts-ignore
geometry: new Point(element.coordinates),
title: element.title,
description: element.description
})
);
});
setFeatures(features);
//@ts-ignore
const collections = new Collection(features);
const vectorLayer = new Vector({
source: new SourceVector({
//@ts-ignore
features: collections
})
});
map.addLayer(vectorLayer);
map.addControl(new MousePosition());
map.addControl(new ScaleLine());
map.setView(new View({
center: [4420562.702930699, 5981642.351758002],
zoom: 17
})
);
}, []);
const addPointToLost = () => {
//@ts-ignore
const newFeature = new Feature({
// @ts-ignore
geometry: new Point(coordinates),
title: title,
description: description
});
**********************************************
//как получить доступ к колекции?
//@ts-ignore
collections.push(newFeature);
setRenderModal({render: false, coordinate: []});
};
const renderModalContent = () => (
<div style={{display: "flex", flexDirection: "column"}}>
<input onChange={(event) => {
setTitle(event.target.value);
}} value={title}/>
<input onChange={((event) => {
setDescription(event.target.value);
})} value={description}/>
<button onClick={() => addPointToLost()}>Save</button>
</div>
);
const renderActualPlaces = () => (
<div style={{position: "relative", zIndex: "0"}} id="map">
<button
onClick={() => setRenderMeasure(true)}
>Измерения
</button>
<ul style={{backgroundColor: "wheat", position: "absolute", top: "0", right: "0", zIndex: "22"}}>
{
pointList.map((element, key) => (
<li key={key} data-coordinates={element.coordinates}
onClick={() => setRenderPointInfo({show: true, feature: {element}})}>
<h1>{element.title}</h1>
<p>{element.description}</p>
</li>
))}
</ul>
</div>
);
return (
<section>
{renderActualPlaces()}
<div id="popup" className="ol-popup">
<a href="#" id="popup-closer" className="ol-popup-closer"></a>
<div id="popup-content">
{renderModal.render ? renderModalContent() : null}
</div>
</div>
<form className="form-inline">
<label>Measurement type </label>
<select id="type">
<option value="length">Length (LineString)</option>
<option value="area">Area (Polygon)</option>
</select>
</form>
</section>
);
}
Ответы (1 шт):
Необходимо добавлять новые Feature в источник VectorSource, привязанный к VectorLayer.
Либо VectorSource сам ведет внутреннюю коллекцию и вы добавляете новые Feature его методами, тогда если он привязан к VectorLayer тот автоматом заметит изменения, либо создаете коллекцию (Collection) сами (она реактивная и будет сообщать источнику о своих изменениях), указываете ее в конструкторе VectorSource и тогда добавляете в нее ее методами.
Способ 1:
const arrayOfFeatures = [] // тут созданные Feature с геометрией
// см. https://openlayers.org/en/latest/apidoc/module-ol_source_Vector-VectorSource.html
const vectorSource = new VectorSource({
features: arrayOfFeatures
})
...
// для добавления в источник
vectorSource.addFeature(newFeature)
// для удаления из источника
vectorSource.removeFeature(featureToRemove)
// для очистки источника
vectorSource.clear()
Способ 2:
const arrayOfFeatures = [] // тут созданные Feature с геометрией
// см. https://openlayers.org/en/latest/apidoc/module-ol_Collection-Collection.html
const collection = new Collection(arrayOfMeatures)
const vectorSource = new VectorSource({
features: collection
})
...
// для добавления в коллекцию
collection.push(newFeature)
// для удаления из коллекции
collection.remove(featureToRemove)
// для очистки коллекции
collection.clear()