1

So, I have a set of roads that have two configurations, a straight line, and a "snap to road" line, where the user can change between them by clicking the road icon on the toolbar. In order to make it performative, I'm deleting the existing layer to then render the next one.

At first, I tried to hide it with CSS (which worked), but it made the map pretty slow, so I wanted to move on in this path where only the needed info is displayed on the map. The problem is, even though the layers are being updated behind the scene, the map is still displaying the old information, not changing after the first successful render.

So here is how the map is first rendered:

Here you can see the starting map

And here is after the first time you press the "straight line" switcher:

enter image description here

So far it works great, but after that, no map manipulations work, the depot (green marker) can't be hidden and the routes can't go back to "snap to road" mode. I've logged the layers from the map, after the changes, and they are all updated to the supposed state, but the map on its own is not being updated.

This is the code to delete the layers:

let straightRoutes = [...map.getLayers().getArray()].filter((layer: any) => layer.getClassName() === 'straight')
let snapRoutes = [...map.getLayers().getArray()].filter((layer: any) => layer.getClassName() === 'snap')

async function clearLayer() {
  straightRoutes.forEach(async (layer: any) => {
    await map.removeLayer(layer)
  })

  snapRoutes.forEach(async (layer: any) => {
    await map.removeLayer(layer)
  })
}

And this is the code for the route rendering. Please note that there are two functions, one that renders the straight lines and one for the snap to road lines. The below code is run after all the layers have been removed.

function renderStraightRoutes() {
  markers.forEach((route: any) => {
    const vectorSource = new VectorSource()
    
    const selectedStopPaths = showDepot
      ? route.routes
      : route.routes.slice(1, route.routes.length - 1);

    selectedStopPaths.forEach((polyline: any) => {
      let straight = [olProj.fromLonLat([polyline.from_lng, polyline.from_lat]), olProj.fromLonLat([polyline.to_lng, polyline.to_lat])]

      var straightFeature = new Feature({
        geometry: new LineString(straight),
        name: 'Line',
      })

      vectorSource.addFeature(straightFeature)
    })

    const vectorLayer = new VectorLayer({
      source: vectorSource,
      style: getStyle(route.color),
      className: 'straight'
    });

    vectorLayer.setZIndex( 0 )
    map.addLayer(vectorLayer)
  })
}
2
  • It should be sufficient to use layer.setVisible() to show and hide layers. OpenLayers will not render layers which it knows should not be visible, but it won't know if you have hidden the canvas using css.
    – Mike
    Nov 23, 2020 at 14:19
  • I don't know if I'm remembering right, but I've tried with setVisible and it did not have any change whatsoever in the layers, they were still showing up Nov 23, 2020 at 14:42

1 Answer 1

0

There is actually no gain from the use of async await in order to remove layers from the map. You could just loop the layer array and remove each layer one by one. Something like this:


map.getLayers().getArray().map(layer => {
    map.removeLayer(layer);
    return true;
});

Or, in order to avoid extra calls to re-render the layers, just set the layers visibility to false like so:

map.getLayers().getArray().map(layer => {
    layer.setVisible(false);
    return true;
});

Setting the visibility though to false, will keep the layer mounted on the map so this might be a performance concern. If there isn't some kind of forgotten css that you already wrote and that interferes with the layer operations, this approach has to work no matter what because it is the suggested way to remove or hide a layer.

1
  • The only problem is that we have more than 750+ markers, with pretty detailed coordinates for the routes. We would have to display the markers + the two route layers, so the performance would be pretty slow. The way I solved it was just completely deleting the map and rendering another one when needed. Not the best or even a good solution, but performance-wise, it was the only acceptable one. Nov 25, 2020 at 13:26

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.