Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

createLayer function #156

Closed
KubaLorenc opened this issue Dec 29, 2022 · 3 comments
Closed

createLayer function #156

KubaLorenc opened this issue Dec 29, 2022 · 3 comments

Comments

@KubaLorenc
Copy link

KubaLorenc commented Dec 29, 2022

Describe the problem

In esri-leaflet, when we create tile using esriLeaflet.tiledMapLayer({options}), we can actually override the createTile function and for example fetch data from local storage instead of api. Unfortunatelly I don't see how we could do that with esri-leaflet-vector, since esriLeaflet.vectorTileLayer() doesn't seem to trigger createTile . Is there any equivalent of createTile for the VectorTileLayer class?

Describe the proposed solution

Solution would be to provide info of what function is triggered to fetch data from api
Edit:
there is a thread on maplibre github concernig this problem: maplibre/maplibre-gl-js#29
I tried to wire that into the MaplibreGLJSLayer in _initGL function but with little luck

  _initGL: function() {
      var center = this._map.getCenter();
      var options = extend({}, this.options, {
        container: this._container,
        center: [center.lng, center.lat],
        zoom: this._map.getZoom() - 1,
        attributionControl: false
      });
      maplibreGl.addProtocol('custom', (params, callback) => {
        fetch('https://${params.url.split('://')[1]}')
          .then(t => {
            if (t.status == 200) {
              t.arrayBuffer().then(arr => {
                callback(null, arr, null, null);
              });
            } else {
              callback(new Error('Tile fetch error: ${t.statusText}'));
            }
          })
          .catch(e => {
            callback(new Error(e));
          });
        return { cancel: () => {} };
      });
    this._glMap = new maplibregl.Map({
      container: this._container,
      style: {
        version: 8,
        sources: options.style.sources,
        layers: options.style.layers,
        sprite: options.style.sprite,
        glyphs: options.style.glyphs
      },
      center: options.center,
      zoom: 13,
      minZoom: 13,
      maxZoom: 13
    });

    let map = this._glMap;
    map.on('load', () => {
      map.addSource('test-source', {
        type: 'vector',
        tiles: [
          'custom://basemaps.arcgis.com/arcgis/rest/services/OpenStreetMap_v2/VectorTileServer/tile/{z}/{y}/{x}.pbf'
        ],
        minzoom: 13,
        maxzoom: 13,
        format: 'pbf'
      });
      map.addLayer({
        id: 'test-layer',
        type: 'circle',
        source: 'test-source',
        'source-layer': 'mapillary-images',
        paint: {
          'circle-radius': 10,
          'circle-color': '#ff0000'
        }
      });
    });
    this._glMap.once(
      'styledata',
      function(res) {
        this.fire('styleLoaded');
      }.bind(this)
    );
    this._glMap.transform.latRange = null;
    this._glMap.transform.maxValidLatitude = Infinity;

    this._transformGL(this._glMap);

    if (this._glMap._canvas.canvas) {
      this._glMap._actualCanvas = this._glMap._canvas.canvas;
    } else {
      this._glMap._actualCanvas = this._glMap._canvas;
    }
    var canvas = this._glMap._actualCanvas;
    DomUtil.addClass(canvas, 'leaflet-image-layer');
    DomUtil.addClass(canvas, 'leaflet-zoom-animated');
    if (this.options.interactive) {
      DomUtil.addClass(canvas, 'leaflet-interactive');
    }
    if (this.options.className) {
      DomUtil.addClass(canvas, this.options.className);
    }
  }

Alternatives considered

No response

Additional Information

No response

@patrickarlt
Copy link
Contributor

@KubaLorenc I think we need to decide what the use case for this is. The purpose of L.esri.vectorTileLayer is specially to communicate with Vector tile services hosted in ArcGIS. Loading data from somewhere like local storage doesn't interact with the service and might be beyond the scope of what we need to handle in this plugin.

It also might be possible to achieve the same thing with ServiceWorkers which could intercept the network requests.

@KubaLorenc
Copy link
Author

@patrickarlt @dpraimeyuu @axelio Hi, thanks for your reply:)
I wondered because from what I understand esri-leaflet-vector delegates communication with ArcGIS to maplibre. And since we would rather not use SW for this offline functionality we thought that introducing some hook to intercept the communication with ArcGis would be the best and cleanest solution. I also think that this would be quite usefull functionality. So, my question is if you could provide me with some tips/ideas how to achieve this? This is already mentioned in some issues on maplibre-gl-js and since you are using maplibre in your solution i thought maybe there is a chance you could include it in your library.
maplibre/maplibre-gl-js#207 (comment)
mapbox/mapbox-gl-js#2920 (comment)
maplibre/maplibre-gl-js#29

@patrickarlt
Copy link
Contributor

@KubaLorenc it seems like in maplibre/maplibre-gl-js#207 (comment) it was recommended to solve the problem of tile access offline with a ServiceWorker. Looking at your code I don't really see any reason why it shouldn't work. Without a specific example or error messages I don't have much to go on.

The main benefit of using a ServiceWorker would be that Service workers are designed to transparently intercept and modify network requests which is exactly what you want to do:

  1. Cache tile responses in localstorage
  2. Intercept tile requests and serve them from localstorage

I don't think anything would be required in this library if you used ServiceWorkers to do this.

@gavinr gavinr closed this as completed Mar 27, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants