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

Dynamically rendered RasterLayer does not display on Android #486

Open
atkingtornado opened this issue Nov 9, 2024 · 2 comments
Open

Dynamically rendered RasterLayer does not display on Android #486

atkingtornado opened this issue Nov 9, 2024 · 2 comments

Comments

@atkingtornado
Copy link

Hello, I am having an issue that seems to be specific to Android when trying to dynamically render multiple RasterLayer elements. Specifically, the layers do not display on the map, even though I have confirmed that the render function runs (and it works/displays just fine on iOS). If I force a re-draw of MapLibreGL.MapView the layers will show up properly, but this resets the map camera location and flashes to white which is not a great user experience. Here is some example code:

...
  const layerEls = []
  timeMatchTimes.forEach((timeToMatch, i) => {
    let isVisible = false
    if (i === sliderValue) {
      isVisible = true
    }

    let timeIndex = findClosestTimeIndex(dayjs.utc(timeToMatch), layerData.times)
    let time = layerData.times[timeIndex]
    let timeURLStr = dayjs.utc(time).format("YYYYMMDD_HHmmss")

    let layerID = layerData.id + timeURLStr
    let sourceID = layerData.id + timeURLStr + "source"


    let rasterSourceProps = {
      id: sourceID,
      tileUrlTemplates: [
        `https://tiledata.satsquatch.com/tilesdata/${sat+"_"+band}/${sector}/${timeURLStr}/{z}/{x}/{y}.png`,
      ],
      tileSize: 256,
      tms: true
    };

    layerEls.push(
      <MapLibreGL.RasterSource key={sourceID} {...rasterSourceProps}>
          <MapLibreGL.RasterLayer
            key={layerID}
            id={layerID}
            sourceID={sourceID}
            style={{rasterOpacity: isVisible ? 0.8 : 0.0, visibility: isVisible ? "visible" : "none", rasterFadeDuration: 0, rasterOpacityTransition: {duration: 0, delay: 0}}} //
          />
        </MapLibreGL.RasterSource>
    );
  });

  return (
    <>
      {layerEls}
    </>
  )

Is there something special I need to be doing to get this to work on android as expected?

Environment

  • Platform: Android
  • OS version: Android 13
  • Device type: Pixel 5
  • Emulator or Simulator: no
  • Development OS: Windows 11/macOS
  • @maplibre/maplibre-react-native Version: 10.0.0-alpha.24
  • react-native Version: 0.74.5
  • expo Version: 51.0.39

Additional context

I am using Expo development builds on physical devices (ios/android) as well as emulators

@atkingtornado
Copy link
Author

atkingtornado commented Nov 9, 2024

Here is a complete example of what I am referring to: https://github.com/atkingtornado/testrasterlayers

when the "times" state gets updated on button press, the rasterlayer(s) do not render accordingly (https://github.com/atkingtornado/testrasterlayers/blob/master/app/index.tsx)

@KiwiKilian
Copy link
Collaborator

Was able to reproduce, can only make it visible with changing the key of MapView on Android.

Adapted your example to be used within the BugReport template:

import MapLibreGL from "@maplibre/maplibre-react-native";
import React, { useState } from "react";
import { StyleSheet, Text, TouchableOpacity, View } from "react-native";

MapLibreGL.setAccessToken(null);

const styles = StyleSheet.create({
  map: {
    flex: 1,
    alignSelf: "stretch",
  },
  container: {
    position: "absolute",
    bottom: 90,
    right: 20,
    zIndex: 9999,
  },
  button: {
    padding: 10,
    backgroundColor: "white",
    borderRadius: 5,
    borderColor: "rgba(25, 118, 210, 0.2)",
    borderWidth: 1,
  },
  icon: {
    width: 32,
    height: 32,
  },
});

const sat = "GOES16";
const band = "14";
const sector = "CONUS";

export default function Index() {
  const [times, setTimes] = useState([]);

  const onPress = async () => {
    console.log("Press " + times.length);

    if (times.length === 0) {
      console.log("we try....");

      try {
        const response = await fetch(
          "https://tiledata.satsquatch.com/tilesdata/GOES16_14_CONUS.json",
        );

        console.log("We got response!");

        if (!response.ok) {
          throw new Error("Network response was not ok " + response.statusText);
        }

        console.log("Get JSON");
        const data = await response.json();

        console.log(JSON.stringify(data));
        console.log(JSON.stringify(data.times.slice(-10)));
        setTimes(data.times.slice(-10));
      } catch (error) {
        console.error("There was a problem with the fetch operation:", error);
      }
    } else {
      setTimes([]);
    }
  };

  console.log("Showing: " + times.length);

  return (
    <View
      style={{
        flex: 1,
        justifyContent: "center",
        alignItems: "center",
      }}
    >
      <IconButton onPress={onPress} />
      <MapLibreGL.MapView
        key={1}
        style={styles.map}
        logoEnabled={false}
        compassEnabled
        attributionPosition={{ top: 18, left: 18 }}
        styleURL="https://basemaps.cartocdn.com/gl/dark-matter-gl-style/style.json"
      >
        {times.map((timeURLStr, i) => {
          console.log("rendering " + i);
          const isVisible = i === 0;

          const sourceID = sat + timeURLStr + "source";
          const layerID = sat + timeURLStr + "layer";

          return (
            <MapLibreGL.RasterSource
              key={sourceID}
              id={sourceID}
              tileUrlTemplates={[
                `https://tiledata.satsquatch.com/tilesdata/${sat + "_" + band}/${sector}/${timeURLStr}/{z}/{x}/{y}.png`,
              ]}
              tms
              tileSize={256}
            >
              <MapLibreGL.RasterLayer
                key={layerID}
                id={layerID}
                sourceID={sourceID}
                style={{
                  rasterOpacity: isVisible ? 0.8 : 0.0,
                  visibility: isVisible ? "visible" : "none",
                  rasterFadeDuration: 0,
                  rasterOpacityTransition: { duration: 0, delay: 0 },
                }}
              />
            </MapLibreGL.RasterSource>
          );
        })}
      </MapLibreGL.MapView>
    </View>
  );
}

type IconButtonProps = {
  onPress: () => void;
};

const IconButton = ({ onPress }: IconButtonProps) => {
  return (
    <View style={styles.container}>
      <TouchableOpacity onPress={onPress} style={styles.button}>
        <Text>Test</Text>
      </TouchableOpacity>
    </View>
  );
};

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants