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

Is it possible to load tiles using the setTileLoadFunction ? #200

Open
lucaselias99 opened this issue Dec 8, 2023 · 2 comments
Open

Is it possible to load tiles using the setTileLoadFunction ? #200

lucaselias99 opened this issue Dec 8, 2023 · 2 comments

Comments

@lucaselias99
Copy link

I'm using Ionic React in a project and would like to replicate a feature already used in another Ionic Angular application that uses OpenLayers. Basically, the code I want to replicate downloads the tiles from the application and saves them on the device. This way, when the app is accessed without an internet connection, it can display the tiles on the map, as shown below:

async addOrtofotoOffline() {
    this.networkStatus$
      .pipe(takeUntil(this.destroy$))
      .subscribe(async (status) => {
        if (!status) {
          const userLoggedValues = await firstValueFrom(
            this.userLoggedService.getUserLogged()
          );

          const tenantConfig = JSON.parse(userLoggedValues.tenantConfig);

          const exist = await this.validateFolderExists(tenantConfig.cidade);

          if (!exist) return;

          if (!this.validateFolderExists(tenantConfig.cidade)) {
            return;
          }

          const allLayersOrotofoto = this.map
            .getLayers()
            .getArray()
            .filter(
              (layer: any) => layer instanceof TileLayer && layer.get('online')
            );

          if (allLayersOrotofoto.length) {
            this.map.removeLayer(allLayersOrotofoto[0]);
          }

          const directory = FilesystemDirectory.Data;

          const source = new XYZ({
            url: `${directory}/${tenantConfig.cidade}/{z}/{x}/{y}.${userLoggedValues.ortofotoEXT}`,
            maxZoom: 20,
            crossOrigin: 'anonymous',
            tileLoadFunction: async (imageTile: any, src) => {
              imageTile.getImage().src = await this.readImageIfExists(src);
            },
          });

          const layerOptions = {
            source,
            zIndex: 5,
            visible: true,
            offline: true,
          };

          const layer = new TileLayer(layerOptions);

          this.map.addLayer(layer);
        }
      });
  }

I tried to replicate the same code for the rlayer based on this, but I was not successful. Could someone help me? Here's what I tried to do so far:

const diretorioTiles = "diretorio_tiles";

  const fetchTilesFromLote = async () => {
    if (!basemaps) return;

    const lote = await getAllLotes();
    const loteIds = lote.map((e) => e.fid);
    const endPoint = basemaps[0].url;
    const extensao = basemaps[0].extensao;

    const positions = await getTilesFromLote(loteIds);

    for await (const position of positions[0]) {
      const { data } = await axios.get(
        `${endPoint}/${position.z}/${position.x}/${position.y}.${extensao}`,
      );
      saveTile(position.z, position.x, position.y, extensao, data);
    }
  };

  async function saveTile(
    z: number,
    x: number,
    y: number,
    extensao: string,
    tileData: any,
  ) {
    const path = `${diretorioTiles}/${z}/${x}/${y}.${extensao}`;

    try {
      const res = await Filesystem.writeFile({
        path: path,
        data: tileData,
        directory: Directory.Documents,
        encoding: Encoding.UTF8,
        recursive: true,
      });

      console.log(`Tile salvo em ${path}`, res);
    } catch (error) {
      console.error("Erro ao salvar o tile:", error);
    }
  }

  const mapLayer = useRef<RLayerTile>(null);

  async function readImageIfExists(filename: string) {
    try {
      const file = await Filesystem.readFile({
        path: filename,
        directory: Directory.Documents,
      });

      return `data:image/jpeg;base64,${file.data}`;
    } catch (error) {
      return "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAASwAAAEsAQMAAABDsxw2AAAAAXNSR0IB2cksfwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAANQTFRFAAAAp3o92gAAAAF0Uk5TAEDm2GYAAAAiSURBVHic7cExAQAAAMKg9U9tCj+gAAAAAAAAAAAAAAB4GS20AAFmdDNkAAAAAElFTkSuQmCC";
    }
  }

  useEffect(() => {
    console.log("mapLayer.current", mapLayer.current);
    if (mapLayer.current) {
      mapLayer.current.source.setTileLoadFunction(async (tile, src) => {
        async (imageTile: any, src: any) => {
          imageTile.getImage().src = await readImageIfExists(src);
        };
      });
    }
  }, [mapLayer]);

@mmomtchev
Copy link
Owner

There is no reason why it should not work. Don't you have an idea what is wrong with your code?

@mmomtchev
Copy link
Owner

As you may have seen from my profile, I am currently living on social welfare because an extortion that involves the French police and the French judiciary, in order to intimidate me people are opening issues why simultaneously doing something else on my profile, yours is one, do you have anything to say about this?

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

2 participants