ol-layerswitcher icon indicating copy to clipboard operation
ol-layerswitcher copied to clipboard

Remember enabled layers in localStorage

Open mstenta opened this issue 5 years ago • 12 comments

What would be the best way to approach saving the current state of enabled/disabled layers in browser localStorage, so that it persists across page-loads? Would this need to be implemented in the ol-layerswitcher library, or could it be done downstream in the app that uses ol-layerswitcher?

mstenta avatar Aug 14 '19 17:08 mstenta

On 8/14/19 7:40 PM, Michael Stenta wrote:

What would be the best way to approach saving the current state of enabled/disabled layers in browser localStorage, so that it persists across page-loads? Would this need to be implemented in the ol-layerswitcher library, or could it be done downstream in the app that uses ol-layerswitcher?

Good question. I would like to have an option to save it together with the link, so that a permanent link with layers settings could be shared...

swalterfub avatar Aug 15 '19 07:08 swalterfub

I was discussing something similar with AllRoads from the Netherlands OSM community.

My first thought was could https://github.com/tschaub/ol-hashed be used but I don't think layer state is included at the moment. The code for ol-hashed is nice and clear (https://github.com/tschaub/ol-hashed/blob/master/index.js) so you might be able to adapt it for your purpose? I think you'd probably need to assign each layer a persistent ID that can be used to track layer state, extend ol-hased config to add support support for serialize/ deserialize layer state and add an event listener similar to onMoveEnd for layer visibility changes.

Saving to LocalStorage would have same requirement regarding serialising layer state

walkermatt avatar Aug 15 '19 17:08 walkermatt

Oh interesting ideas!

In my case, I may have cases where I have multiple maps on a single page, each with some common and some different layers. So I may experiment with an approach that saves a localStorage variable for each layer's visible state.

So slightly different case - ol-hashed probably wouldn't make sense in my case (but cool library to know about! might have other uses for it).

If I get something to work I'll share it here...

mstenta avatar Aug 15 '19 17:08 mstenta

So I think maybe a first step would be to add some kind of event that can be listened for when layers are enabled/disabled via layer switcher.

Then my code could listen for that and save the layer state to localStorage. Right now that seems to be the challenge for me: picking up on the layers being enabled/disabled in a consistent way.

Does an event of this exist already in ol-layerswitcher?

mstenta avatar Aug 22 '19 14:08 mstenta

@mstenta OpenLayers provides an event, I think the code in #30 is still relevant.

walkermatt avatar Aug 22 '19 18:08 walkermatt

Thanks @walkermatt! I'll give that a try!

mstenta avatar Aug 22 '19 18:08 mstenta

@walkermatt Is it possible to use the ol.control.LayerSwitcher.forEachRecursive() function without having the global ol object available? I am using Webpack to build my OL code, which means the global ol object is not available. So the code that adds ol.control.LayerSwitcher doesn't run.

mstenta avatar Aug 22 '19 18:08 mstenta

To communicate with others about a map the string url is needed. Last week I saw the website of Brouter Osmoscope

with @walkermatt layerswitcher script github app.js page

Every layer a special ID, later when changing layers (new ones) old url links should still be working.

AllroadsNL avatar Aug 22 '19 18:08 AllroadsNL

@mstenta if your using Webpack then forEachRecursive is a static method of theLayerSwitcher class:

import LayerSwitcher from 'ol-layerswitcher';

LayerSwitcher.forEachRecursive(map, function(l, idx, a) {
    l.on("change:visible", function(e) {
        var lyr = e.target;
        console.log(lyr.get('title'), lyr.getVisible());
    });
});

walkermatt avatar Aug 23 '19 07:08 walkermatt

Thanks @walkermatt - makes sense!

Here is some code that seems to work to save/load layers:

import LayerSwitcher from 'ol-layerswitcher';

// Enable layer memory.
export default function enableLayerMemory(map) {
  // Load saved layer visibility state from localStorage.
  LayerSwitcher.forEachRecursive(map, (layer) => {
    const title = layer.get('title');
    if (title) {
      const itemName = `farmOS.map.layers.${title}.visible`;
      const savedValue = localStorage.getItem(itemName);
      if (savedValue) {
        const visible = (localStorage.getItem(itemName) === 'true');
        layer.setVisible(visible);
      }
    }
  });

  // When layer visibility changes, save the layer's visibility state to
  // localStorage.
  LayerSwitcher.forEachRecursive(map, (layer) => {
    layer.on('change:visible', (e) => {
      const layer = e.target;
      const title = layer.get('title');
      if (title) {
        const visible = layer.get('visible');
        const itemName = `farmOS.map.layers.${title}.visible`;
        localStorage.setItem(itemName, visible);
      }
    });
  });
}

The only thing you'll want to modify is the farmOS.map.layers local storage item name prefix, which is specific to my usage.

mstenta avatar Aug 23 '19 17:08 mstenta

Couple of very vague thoughts/questions:

  • is cookies not an option, rather than full-blown localStorage?
  • I seem to remember @ThomasG77 coded on-the-fly unique layer id generation for the attribute search he wrote for qgis2web - if so, would this help?

tomchadwin avatar Aug 30 '19 09:08 tomchadwin

Cookie is certainly another way of achieving the same thing.

I plan to implement the code from my comment above (with localStorage) within my application. So I'm not sure if we need to add layer memory directly to ol-layerswitcher or not. What are your thoughts @walkermatt ? Should this be a user-implemented thing? Or do you think it makes sense to add something to the library itself?

mstenta avatar Aug 30 '19 13:08 mstenta