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

Custom openlayers loader function #252

Closed
packetstracer opened this issue Mar 24, 2020 · 2 comments
Closed

Custom openlayers loader function #252

packetstracer opened this issue Mar 24, 2020 · 2 comments

Comments

@packetstracer
Copy link

packetstracer commented Mar 24, 2020

It would be great to give the posibility to provide an openlayers custom loader function to source components (or whereever needed) in order to access gis servers with specific requirements or handle requests in a customize way.

I could do the development if indications given, don't know where to start. I'll try to include the functionality because I need it in my currrent project and will provide the result in here.

Any help would be apreciated.

@packetstracer
Copy link
Author

packetstracer commented Mar 27, 2020

I'm doing a first try and think that can be done by modifying tileLoadFunction in source parameter passed to _register method in source.component.ts before setting the source to openlayers instance. Something like this seems to work with a xyz-source:

  protected _register(source: any) {
    const token = 'my-token';

    // function for AJAX request (this should be part of tileLoadFunction)
    const request = (url, token) => {
      return new Promise((resolve, reject) => {
        const xhr = new XMLHttpRequest();
        xhr.onreadystatechange = () => {
          if (xhr.readyState === 4 && xhr.status === 200) {
            resolve(xhr);
          } else if (xhr.readyState === 4 && xhr.status !== 200) {
            reject(Error(xhr.statusText));
          }
        };
        xhr.open('GET', url);
        xhr.responseType = 'blob';
        xhr.setRequestHeader('Authorization', 'Bearer ' + token);
        xhr.send();
      })
    };

    // openlayers custom load function, should be passed  as a parameter or already set as source.tileLoadFunction
    const tileLoadFunction = (imageTile: any, url) => {
      request(url, token)
        .then((xhr: any) => {
          const resp = xhr.response;
          const imagen = URL.createObjectURL(resp);
          imageTile.getImage().src = imagen;
          URL.revokeObjectURL(resp);
        })
        .catch(() => {
          imageTile.getImage().src = '#';
        })
    }

    if (this.host) {
      // set the function as source.tileLoadFunction
      source.tileLoadFunction = tileLoadFunction;
      this.host.instance.setSource(source);
    }

    if (this.raster) {
      this.raster.sources = [source];
    }
  }

My Idea is to add an @input property in xyz.component so the function can be passed when using the component as this:

  <aol-layer-tile [visible]="true">
    <aol-source-xyz
      url="https://my-server.com/{z}/{x}/{y}.png"
      [tileLoadFunction]="myCustomTileLoadFunction"
      opaque="false"
      crossOrigin=""
    >
    </aol-source-xyz>
  </aol-layer-tile>

and then set to the source object in one this 2 places:

  • xyz.component.ngAfterContentInit()
  • source.component._register()

I also guess, that this functionality could be added to other source components, but do not know which ones should support this kind of functionality.

Any thoughts on this approach?

Thanks

@packetstracer
Copy link
Author

packetstracer commented Apr 16, 2020

Finally I found that the xyz component has a property for that

@Input() tileLoadFunction?: TileLoadFunctionType;

also de geoson component has a property for that

@Input() loader?: ol.FeatureLoader;

but in the second case I needed to acces geojson component openlayers instance property inside de loader function, so I needed to modify slightly de component ngOnInit() method. The resulting code is this for geojson.component.ts

    ngOnInit() {
        // @NOTE loader function is binded to this in order to have access to this.intance when executing the loader function
        this.loader = this.loader.bind(this);
        this.format = new format.GeoJSON();
        this.instance = new source.Vector(this);

        this.host.instance.setSource(this.instance);
    }

I also have to solve some typescript errors due to using the library source code in my Angular 8 aplication.

If you want a pull request or integrate the changes in the library just let me know.

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

1 participant