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 &nbsp;</label>
        <select id="type">
          <option value="length">Length (LineString)</option>
          <option value="area">Area (Polygon)</option>
        </select>
      </form>

    </section>
  );

}


Ответы (1 шт):

Автор решения: t0lik

Необходимо добавлять новые 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()

→ Ссылка