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

[Bug]: Local Filesystem raster tiles #3323

Open
Cdingram opened this issue Jan 15, 2024 · 1 comment
Open

[Bug]: Local Filesystem raster tiles #3323

Cdingram opened this issue Jan 15, 2024 · 1 comment
Labels
bug 🪲 Something isn't working

Comments

@Cdingram
Copy link
Contributor

Cdingram commented Jan 15, 2024

Mapbox Implementation

Mapbox

Mapbox Version

default

Platform

Android

@rnmapbox/maps version

10.1.6

Standalone component to reproduce

import React, { useEffect} from 'react';
import Mapbox from '@rnmapbox/maps';
import { StyleSheet, View, Alert } from 'react-native';
import * as FileSystem from 'expo-file-system';

const styles = StyleSheet.create({
    map: {
        width: '100%',
        height: '100%',
    }
});

const CreateOfflineMaps = () => {
    const TILE_FOLDER = `${FileSystem.documentDirectory}tiles`;
    const MAP_URL = 'http://c.tile.openstreetmap.org';

    useEffect(() => {
        const test = async () => {
            // check if a test png exists, if not then download them
            const fileInfo = await FileSystem.getInfoAsync(`${TILE_FOLDER}/1/0/0.png`)
            if (!fileInfo.exists) {
                downloadTiles();
            }
        }
        test();
    }, []);

    const downloadTiles = async () => {
        // just a few top level tiles to test
        const tiles = [{ x: 0, y: 0, z: 1 }, { x: 1, y: 1, z: 1 }, { x: 0, y: 0, z: 0 }, { x: 1, y: 0, z: 1 }, { x: 0, y: 1, z: 1 }];

        // Create directory for tiles
        for (const tile of tiles) {
            const folder = `${TILE_FOLDER}/${tile.z}/${tile.x}`
            await FileSystem.makeDirectoryAsync(folder, { intermediates: true })
        }

        // Download tiles in batches to avoid excessive promises in flight
        const BATCH_SIZE = 100

        let batch = []

        for (const tile of tiles) {
            const fetchUrl = `${MAP_URL}/${tile.z}/${tile.x}/${tile.y}.png`
            const localLocation = `${TILE_FOLDER}/${tile.z}/${tile.x}/${tile.y}.png`
            const tilePromise = FileSystem.downloadAsync(fetchUrl, localLocation)
            batch.push(tilePromise)

            if (batch.length >= BATCH_SIZE) {
                await Promise.all(batch)
                batch = []
            }
        }

        await Promise.all(batch)

        alert('Finished downloading tiles.')
    }

    // tile url here can be replace with "http://c.tile.openstreetmap.org/{z}/{x}/{y}.png" and it works fine
    const styleJSON = {
        "version": 8,
        "name": "Offline Test",
        "sources": {
            "offline": {
                "type": "raster",
                "tiles": [
                    `${FileSystem.documentDirectory}tiles/{z}/{x}/{y}.png`
                ]        
            }
        },
        "layers": [{
            "id": "test",
            "type": "raster",
            "source": "offline",
        }]
    }

    return (
        <View style={styles.container}>
            <Mapbox.MapView 
                style={styles.map}
                styleJSON={JSON.stringify(styleJSON)}
            >
            </Mapbox.MapView>
        </View>
    );
}

export default CreateOfflineMaps

Observed behavior and steps to reproduce

If you allow the tiles to be downloaded, and reload or leave and re-enter this component, the app will crash on android (development build for expo).

Here are my relevant package versions (I'm using expo):

"@rnmapbox/maps": "^10.1.6",
"expo": "^49.0.21",
"expo-file-system": "~15.4.5",
"react": "18.2.0",
"react-native": "0.72.6",

Expected behavior

Should just show the map tiles

Notes / preliminary analysis

I don't get any errors from my terminal or anything really, it simply crashes. The code works fine if you replace the tile url with an online one like "http://c.tile.openstreetmap.org/{z}/{x}/{y}.png" and it also works as expected with the downloaded tiles on iOS.

Additional links and references

I am trying to do something similar to what is done here and downloading tiles based on this tutorial (this part works great).

@Cdingram
Copy link
Contributor Author

I'm sure it could be reproduced without expo if you are able to just place some downloaded tiles in any file:// location and reference it in the tiles array like above.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug 🪲 Something isn't working
Projects
None yet
Development

No branches or pull requests

1 participant