0

enter image description here

I have a list of layers drawn on the map with their geometry and other data. I want to change the style of those point whenever I click the name om the left. I have the event but I dont know how to change the style of already drawn layer.

This is the part of my code that I tried:

export const SearchItem = ({ data, map }) => {
    const [isShown, setIsShown] = useState(false)
    if (isShown) {
        const format = new Format()
        const feature = format.readFeature(data.geom, {
            dataProjection: "EPSG:4326",
            featureProjection: "EPSG:3857",
        })
        let vectorSource = new VectorSource({
            features: [feature],
        })
        let vectorLayer = new VectorLayer({
            source: vectorSource,
            displayInLayerSwitcher: false,
            style: new Style({
                fill: new Stroke({
                    color: "#FF5733",
                }),
                stroke: new Stroke({
                    color: "#FF5733",
                    width: 5,
                }),
            }),
        })
        const select = new Select({
           layers: [vectorLayer],
        })
        map.addInteraction(select)
    }

    return (
        <div
            onMouseEnter={() => setIsShown(true)}
            onMouseLeave={() => setIsShown(false)}
            className="product-item"
        >
            <div className="product-list-detail">
                <h5 className="p-mb-2">{data.yurt_ad}</h5>
                <i className="pi pi-phone product-category-icon"></i>
                <span className="product-category">{data.telefon}</span>
                <div className="search-item-address">
                    <i className="pi pi-map-marker product-category-icon"></i>
                    <span className="product-category">{data.adres}</span>
                </div>
            </div>
        </div>
    )
}

So this code is the part when clicked on the list on each name which will gives me the geometry of that layer. Since I have the Geometry of the clicked layer, it should be possible to change its style on the map.

Am I wrong?

9
  • You can change the style of the feature/geometry if you can identify it when clicking on menu. There should be some property of clicked menu item that can identify feature by it's id, see openlayers.org/en/latest/apidoc/…
    – TomazicM
    Commented Dec 27, 2021 at 10:18
  • I tried feature.setStyle() but doesnt work.
    – Angels
    Commented Dec 27, 2021 at 10:21
  • Where did you get your feature from?
    – TomazicM
    Commented Dec 27, 2021 at 10:28
  • from the list shown on the left.
    – Angels
    Commented Dec 27, 2021 at 10:50
  • data.name is shown on the list and data.geom is the geometry pf each data from the list
    – Angels
    Commented Dec 27, 2021 at 10:51

1 Answer 1

0

I'm not sure if I follow logic of your existing code and I'm also not at home in JS ES6, so I hope my attempt to answer will help you solve your problem.

To access feature from inside click processing function changeFeatureStyle, some feature id is needed by which it can be retrieved. Method .setId is used to set feature id and method .getFeatureById is used to retrieve desired feature from layer source. To make layer source reachable inside click processing function, layer variable has to be global.

To get unique id for feature, simple hash function hashCode is used that calculates id from feature geometry string.

Logic of the code below is following:

  • click on item sets desired feature style to selectedStyle;
  • if some other item was selected at time of the click, it's style is cleared;
  • if clicked item is already selected, it is deselected.

Code could then look something like this:

let vectorSource = new ol.source.Vector();
let vectorLayer = new ol.layer.Vector({
  source: vectorSource,
  style: new ol.style.Style({}),
  displayInLayerSwitcher: false,
});
map.addLayer(vectorLayer);

const selectedStyle = new ol.style.Style({
  fill: new ol.style.Stroke({
    color: "#FF5733",
  }),
  stroke: new ol.style.Stroke({
    color: "#FF5733",
    width: 5,
  }),
});

var selectedFeatureId = null;

function changeFeatureStyle(featureId) {
  const feature = vectorSource.getFeatureById(featureId);
  var selectedFeature = null;

  if (selectedFeatureId) {
    selectedFeature = vectorSource.getFeatureById(selectedFeatureId);
    selectedFeature.setStyle();
    selectedFeatureId = null;
  }
  if (!selectedFeature || (selectedFeature.getId() != feature.getId())) {
    feature.setStyle(selectedStyle);
    selectedFeatureId = feature.getId();
  }
}
 
function hashCode(s) {
  var h = 0, l = s.length, i = 0;
  if ( l > 0 )
    while (i < l)
      h = (h << 5) - h + s.charCodeAt(i++) | 0;
  return Math.abs(h);
}

function searchItem(data) {
  const format = new ol.format.GeoJSON();
  const feature = format.readFeature(data.geom)
  const featureId = hashCode(JSON.stringify(data.geom));
  feature.setId(featureId);
  vectorSource.addFeature(feature);
  return (
      `<div
          className="product-item" 
          onclick="changeFeatureStyle(` + featureId + `)"
       >
          <div className="product-list-detail">
              <h5 className="p-mb-2">` + data.yurt_ad + `</h5>
              <i className="pi pi-phone product-category-icon"></i>
              <span className="product-category">` + data.telefon + `</span>
              <div className="search-item-address">
                  <i className="pi pi-map-marker product-category-icon"></i>
                  <span className="product-category">` + data.adres + `</span>
              </div>
          </div>
      </div>`
  )
}

Since selection layer vectorLayer is global, it's source should be cleared before every new search.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.