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

Z-index issue on re-render with <UrlTile/> and <Polyline/> #1181

Closed
dbrugne opened this issue Mar 30, 2017 · 25 comments
Closed

Z-index issue on re-render with <UrlTile/> and <Polyline/> #1181

dbrugne opened this issue Mar 30, 2017 · 25 comments
Labels

Comments

@dbrugne
Copy link

dbrugne commented Mar 30, 2017

I've a got a use case where I have to display different cartography (from Gmap, Geoportail and custom tile server) as fullscreen and with some markers and polygons drawn on map.

I'm using MapView, UrlTitle, Circle and Polyline.

On first render I render the following tree and both MapView, UrlTitle, Marker, Circle and Polyline are displayed:

<MapView
  style={styles.map}     // map: { ...StyleSheet.absoluteFillObject }
  showsUserLocation
  showsTraffic={false}
  showsIndoors={false}
>
  <UrlTile urlTemplate={openStreetMapUrlTemplate} />
  <Circle
    center={coords}
    radius={5000}
    strokeColor="red"
  />
  <Polyline
    coordinates={droneCoords}
    strokeWidth={2}
    lineCap="round"
    lineJoin="round"
    lineDashPhase={3}
    lineDashPattern={[3]}
  />
  <Marker
    coordinate={droneCoords[0]}
    image={require('./assets/drone-100.png')}
  />
</MapView>

When user change cartography to display (via a menu) it triggers a re-render of my component with a new (or additionnal) UrlTile:

<MapView
  style={styles.map}     // map: { ...StyleSheet.absoluteFillObject }
  showsUserLocation
  showsTraffic={false}
  showsIndoors={false}
>
  <UrlTile urlTemplate={geoportailIgnUrlTemplate} /> {/* new urlTemplate */}
  <Circle
    center={coords}
    radius={5000}
    strokeColor="red"
  />
  <Polyline
    coordinates={droneCoords}
    strokeWidth={2}
    lineCap="round"
    lineJoin="round"
    lineDashPhase={3}
    lineDashPattern={[3]}
  />
  <Marker
    coordinate={droneCoords[0]}
    image={require('./assets/drone-100.png')}
  />
</MapView>

Everything works fine excepts that the new tiles are displayed over Polyline and Circle that are hidden. But not upon Marker that is still correctly displayed.

It seems like a z-index issue and uniquely when you vary UrlTile between different renders.

My workaround (until a definitive fix) will be to force a new MapView re-rendering.

Tested on iOS simulator iPhone 6/ iOS 10.2.

@dbrugne dbrugne changed the title Re-render of the same <MapView/> with <UrlTitle/> and <Polyline/> draw tile upon Z-index issue on re-render with <UrlTile/> and <Polyline/> Mar 30, 2017
@markmssd
Copy link

I had something similar, and changing the zIndex property of UrlTile to -3 got it properly under the Polyline, after rerenders too.

@markmssd
Copy link

@dbrugne
Maybe you could help me with something. I'm using the UrlTile component, but whenever I change the urlTemplate url through props, it does not update the tiles on the map. How did you get it to remove the old tiles, and replace it with the new ones?
Thanks!

@markmssd
Copy link

Searching in the source code, I noticed the Polyline has a zIndex property as well... I've set it explicitly to 5 and now it's appearing over the Tiles.

Weird behaviour:
Tile's zIndex defaults to -1,
Polyline's zIndex defaults to 0,
but Polyline still appears under the Tile if zIndex is not specified... bug?

@dbrugne
Copy link
Author

dbrugne commented Mar 31, 2017

@markmssd i'm adding/removing on different renders and it update displayed tiles accordingly.

Are you sure that your render() is triggered while your props change?

@dbrugne
Copy link
Author

dbrugne commented Mar 31, 2017

Changing zIndex property on UrlTile, Polyline and Circle hasn't any effect.

It is a real bug.

@markmssd
Copy link

Are you on Android or iOS? I'm on iOS, and after I've added the zIndex on both Tiles and Polyline, the Polyline correctly renders on top of the Tiles.

@markmssd
Copy link

For the tiles not being updated... yes I've put couple of console.logs in the render() function, which is being called properly. I even tried to use forceUpdate() without success.

When you say that you adding/removing on different renders, you mean you're passing in a whole new UrlTile component?

@dbrugne
Copy link
Author

dbrugne commented Mar 31, 2017

My code (also work with inline JSX ternary in render() method:

class MyMap extends Component {
  // ...
    firstOverlay = () => (this.props.mapOverlay === 'first'
    ? <UrlTile urlTemplate={myFirstUrlTemplate} />
    : null);
  secondOverlay = () => (this.props.mapOverlay === 'second'
    ? <UrlTile urlTemplate={myFirstUrlTemplate} />
    : null);
  // ...
  render() {
    return (
      <MapView
        style={styles.map}
        initialRegion={{ ...initilalRegion }}
        showsUserLocation
        userLocationAnnotationTitle="Your position"
        loadingEnabled
        showsTraffic={false}
        showsIndoors={false}
      >
        {this.firstOverlay()}
        {this.secondOverlay()}
        // ...
    </MapView>
    );
  }
}

@markmssd
Copy link

Aah I see! So you're also doing a hackish solution. Ideally, when 'urlTemplate' changes, it should rerender the tiles... I'll use your solution as well for now and when I have time I'll PR a fix for it. Thanks!

PS, any luck with your zIndex? It should work... it's working for me

@Stophface
Copy link
Contributor

Stophface commented Nov 13, 2017

@markmssd lifesaver. Your zIndex solution works. Adding zIndex=999 to the Polyline does not do anything for me.

Regarding the re-rendering problem. Not sure what you guys try to achieve, but sometimes (on Android only as far as i know) the re-rendering, especially of markers, only works when the key changes.
So something like

...
 key={Date.now()}
...

should trigger a re-rendering. That feels a little hacky though and causes react-native to rerender everything everytime. Handle with care!

@systemlevel
Copy link

systemlevel commented Mar 7, 2019

I'm still having an issue trying to control the order of appearance when using two UrlTiles layers.

It doesn't matter which order the UrlTile layers are included, one layer (SECOND) always sits on top of the other.

Example:

// FIRST
<UrlTile
   urlTemplate={'https://tiles.example.com/map/test/Mapnik/{z}/{x}/{y}.png'}
   maximumZ={18}
    zIndex={999}
 />

// SECOND
<UrlTile
   urlTemplate={'https://stamen-tiles.a.ssl.fastly.net/watercolor/{z}/{x}/{y}.jpg'}
   maximumZ={19}
/>

The SECOND UrlTile layer still loads on top of the first one.

I can briefly see the FIRST layer while the SECOND is rendering

@Stophface is your zIndex being set in an UrlTile component? Not sure why I can't get a zIndex working.

Using the latest release.

@markmssd if I understood your comment you indicated there was a PR to fix these issues. Was that also fixing the order of UrlTiles?

@systemlevel
Copy link

I'm still having an issue trying to control the order of appearance when using two UrlTiles layers.

It doesn't matter which order the UrlTile layers are included, one layer (SECOND) always sits on top of the other.

Example:

// FIRST
<UrlTile
   urlTemplate={'https://tiles.example.com/map/test/Mapnik/{z}/{x}/{y}.png'}
   maximumZ={18}
    zIndex={999}
 />

// SECOND
<UrlTile
   urlTemplate={'https://stamen-tiles.a.ssl.fastly.net/watercolor/{z}/{x}/{y}.jpg'}
   maximumZ={19}
/>

The SECOND UrlTile layer still loads on top of the first one.

I can briefly see the FIRST layer while the SECOND is rendering

@Stophface is your zIndex being set in an UrlTile component? Not sure why I can't get a zIndex working.

Using the latest release.

@markmssd if I understood your comment you indicated there was a PR to fix these issues. Was that also fixing the order of UrlTiles?

If I'm understanding the code for UrlTile correctly the zIndex prop is only for Android? So how do you achieve the desired ordering of the layers in iOS? @Stophface

@alexeyvax
Copy link

@systemlevel I think you should try this option:
<UrlTile
urlTemplate={'https://tiles.example.com/map/test/Mapnik/{z}/{x}/{y}.png'}
maximumZ={18}
style={{ zIndex: -1 }}
/>

Just add zIndex into styles

@gangstaJS
Copy link

Any progress. I still have the issue. my Overlay is hiding under UrlTile
https://monosnap.com/file/jJErv8rNf58IIckEhJYBGu7q17WIGd

@remarket-vn
Copy link

remarket-vn commented Mar 17, 2020

zIndex not really work. If you have some elements like:

<MapView>
   <UrlTile />
   <Polyline />
</MapView>

The <Polyline /> always on top. If you add another element, something like <Circle /> or another <UrlTile />, the latest element you've added on top always.
Re-order the position of your elements in your MapView can re-order the layers. No need zIndex.
Hope it helps.

@jgtoriginal
Copy link
Contributor

jgtoriginal commented Jul 7, 2020

Another way to make dynamic UrlTile rendering work as expected.

customTiles
    ? <UrlTile urlTemplate={customMapUrlTemplate} tileSize={256} />
    : <UrlTile urlTemplate={null} tileSize={256} />

Not ideal, but makes rendering order intact.
So any other element -Marker, Polyline, Polygon- doesn't get hidden behind the new tiles.

@jmlavoier
Copy link

I had something similar, and changing the zIndex property of UrlTile to -3 got it properly under the Polyline, after rerenders too.

It worked for me.

@stale
Copy link

stale bot commented Oct 2, 2020

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the stale label Oct 2, 2020
@stale stale bot closed this as completed Oct 10, 2020
@Haseeba393
Copy link

I'm using latest release as well. Passing zIndex as prop in UrlTile or in style object is not working for me. I want to perform a smooth radar animation on google maps. The solution you suggest above to re-render that make a flicker. Any one please help me out?

@Khubaib69
Copy link

@markmssd lifesaver. Your zIndex solution works. Adding zIndex=999 to the Polyline does not do anything for me.

Regarding the re-rendering problem. Not sure what you guys try to achieve, but sometimes (on Android only as far as i know) the re-rendering, especially of markers, only works when the key changes. So something like

...
 key={Date.now()}
...

should trigger a re-rendering. That feels a little hacky though and causes react-native to rerender everything everytime. Handle with care!

Hello, I am also using something similar like this. Basically I am creating this app where there is a slider and when I move the slider, app shows weather for the next hour. UrlTIle is updating thanks to key property, but it takes 2-3 seconds to load the image and show it on map. is there any way in react native where I can achieve this transition smoothly, like in apple weather app?

If anyone know the answer to this please respond!

@Haseeba393
Copy link

@Khubaib69 are you playing an animation for the next hour?

@Khubaib69
Copy link

@Khubaib69 are you playing an animation for the next hour?

No I am not playing any animation. basically, there is a slider when slider is in the middle it shows current(time) weather layer, when slider is moved to the right it shows weather layer for next hour and when it is moved to left it shows the previous hour weather layer. I was able to achieve this by passing timestamp of next hour and previous hour in UrlTile urltemplate when changing slider. but as you said above it causes re-render that make a flicker. Is there any way I can this transition smooth?

@Haseeba393
Copy link

@Khubaib69 yes you can make it smooth. Load all three url tiles (previous hour, current and next hour) on the map. Then use opacity property to display and hide respective layers.

@Steytz
Copy link

Steytz commented Apr 25, 2024

I fixed this for android by setting , for ios i had to do a bit more. I had to force a re render for the component that gets overlapped as soon as the tiles are loaded in combination with a changing key like Date.now(). Only then it worked.

@vjanssens
Copy link

I fixed this for android by setting , for ios i had to do a bit more. I had to force a re render for the component that gets overlapped as soon as the tiles are loaded in combination with a changing key like Date.now(). Only then it worked.

Can you share some code how you did this? I'm still having the same issue. The UrlTile is loaded dynamically based on a boolean useState, which is causing the z-index issue.

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

No branches or pull requests