reactjsopenlayersopenlayers-6

Openlayers imagelayer and imagestatic with custom imageloadfunction not loading if zoomed in?


My problem:

In my react app, I have some functionality that allows for getting an image from an API. If the image is added while the user is above a certain zoomlevel (differs depending on area, ~7.4 in UK and 6.82 in northern Germany for me) the image will not load unless the user zooms out. Once the user has zoomed out past a specific point (I checked, it's literally always the same zoom level in the same rough area, even when I reload the app, but it differs over long distances roughly country-length) the imageLoadFunction will start the request to the API and it works fine after that. I get no error messages, and if I try to load multiple areas while zoomed in, it's like they are all queued until I zoom out and they start downloading.

I have had another person test the app on their PC, and the zoom levels are not exactly the same (for which it works / doesn't work), but they are again consistent in the same general area.

What I expect is that the imageLoadFunction should be executed regardless of the user's zoom level, which is not happening.

If it matters, my implementation of openlayers also utilizes ol-kit (https://github.com/Bayer-Group/ol-kit/)

This image is added using the following functionality

addImageToMap(<params>) {
    const url = `<url>`;

    const imgSource = new OlImageStatic({
      url: url,
      imageExtent: [
        -37441.9223544409, 6708299.891274841, 48375.87197907233,
        6787434.524407205,
      ],
      imageLoadFunction: this.imageLoadFunction,
    });

    const imageLayer = new OlImageLayer({
      title: `UTM${Zone} ${XPosition}-${YPosition} on ${date.slice(0, 10)}`,
      zIndex: 1,
      source: imgSource,
    });

    this.state.map.addLayer(imageLayer);
}

I have created a custom imageLoadFunction:

imageLoadFunction(image, src) {
    const requestOptions = {
      method: "GET",
      mode: "cors",
    };
    
    let loadingText = `downloading preview`;
    let successText = `Finished downloading preview`;
    
    const requestQueryParameters = new URL(src).searchParams.entries();
    
    const dateParameter = Array.from(requestQueryParameters).filter(
      (e) => e[0] === "date"
    );
    
    if (dateParameter.length) {
      const formattedDate = dateParameter[0][1].slice(0, 10);
      loadingText = `Downloading preview of ${formattedDate} in the background`;
      successText = `Finished downloading preview of ${formattedDate}`;
    }
    
    this.state.setInfoMessage(loadingText);
    
    try {
      fetch(src, requestOptions).then(
        (res) => {
          res
            .blob()
            .then(
              (blob) => {
                const file = window.URL.createObjectURL(blob);
                const extentValues = res.headers
                  .get("X-IMAGE-EXTENT")
                  .replace("[", "")
                  .replace("]", "")
                  .split(",")
                  .map((n) => +n);
    
                image.getImage().src = file;
                image.extent = extentValues;
              },
              (error) => this.state.setErrorMessage(error)
            )
            .then(() => this.state.setSuccessMessage(successText));
        },
        (error) => this.state.setErrorMessage(error)
      );
    } catch (error) {
      this.state.setErrorMessage(error);
    }
}

I have tried:

Any help that can point me towards stuff to research (or even fixing the problem outright) is greatly appreciated.

In the meanwhile, I fixed the issue by always animating the view to zoom out to a level that I believe will always enable the imageLoadFunction to execute, and so far it works wonders (except for terrible UX).


Solution

  • Setting image.extent is not the same as specifying imageExtent. If you obtain the extent when you load the source url create the layer then asynchronously create and set the source.

      const imageLayer = new OlImageLayer({
        title: `UTM${Zone} ${XPosition}-${YPosition} on ${date.slice(0, 10)}`,
        zIndex: 1,
      });
    
      fetch(src, requestOptions).then(
        (res) => {
          res
            .blob()
            .then(
              (blob) => {
                const file = window.URL.createObjectURL(blob);
                const extentValues = res.headers
                  .get("X-IMAGE-EXTENT")
                  .replace("[", "")
                  .replace("]", "")
                  .split(",")
                  .map((n) => +n);
                const imgSource = new OlImageStatic({
                  url: file,
                  imageExtent: extentValues,
                });
                imageLayer.setSource(imgSource);
              },