Maps: SymbolLayer heavy flickering on coordinate updates of parent ShapeSource

Created on 12 Oct 2020  Â·  21Comments  Â·  Source: react-native-mapbox-gl/maps

Describe the bug
The content of a SymbolLayer flickers heavily when when the coordinates of the parent ShapeSource shape property are updated.
See the attached gif for a demonstration of the bug.
The flickering also occurs when non animated SymbolLayers appear on the viewport. E.g. the viewport is rotated so that the SymbolLayer is not in the viewport anymore. Everytime the viewport changes again so that the SymbolLayer reappears, it is faded in as if it was loaded for the first time. No matter if the iconOpacityTransition is set to 0 or not.

To Reproduce

  • Create a ShapeSource or an Animated.ShapeSource and add a SymbolLayer or Animated.SymbolLayer as child.
  • Set the iconImage property of the SymbolLayer to an image.
  • dynamically update the coordinates of the ShapeSource shape property
  • the SymbolLayer content flickers
  • if also a textfield is added to the SymbolLayer the flickering gets even worse
import React, { useEffect, useState } from "react";
import MapboxGL from "@react-native-mapbox-gl/maps";
import { point } from "@turf/turf";
import pinIcon from "src/assets/pin.png";

const initialCoordinate = [13.411807, 52.5008788];

const SymbolLayerAnimationTest = () => {
    const [currentCoordinate, setCurrentCoordinate] = useState(
        initialCoordinate
    );

    useEffect(() => {
        const interval = setInterval(() => {
            setCurrentCoordinate((co) => [co[0], co[1] + 0.0001]);
        }, 1000);

        return () => {
            clearInterval(interval);
        };
    }, []);

    return (
        <MapboxGL.MapView style={{ flex: 1 }}>
            <MapboxGL.Camera
                zoomLevel={18}
                centerCoordinate={initialCoordinate}
            />
            <MapboxGL.Images images={{ pinIcon }} />
            <MapboxGL.Animated.ShapeSource
                id="shapeSource"
                shape={point(currentCoordinate)}
            >
                <MapboxGL.Animated.SymbolLayer
                    id="shapePoint"
                    style={{
                        iconImage: "pinIcon",
                        iconOpacityTransition: { duration: 0, delay: 0 },
                        textField: "Test",
                    }}
                />
            </MapboxGL.Animated.ShapeSource>
        </MapboxGL.MapView>
    );
};
export default SymbolLayerAnimationTest;

(edit ferdicus for code example rendering)

Expected behavior
SymbolLayer content should not flicker when coordinate properties of the ShapeSource update.

Screenshots
20201012_123403

Versions (please complete the following information):

  • Android
  • Samsung Galaxy S10e
  • Emulator/ Simulator: [no]
  • react-native-mapbox-gl Version 8.1.0-rc.5
  • React Native Version 0.62.2

Additional context
The problem exist on all tested real Devices and Simulators at least on Android. Not yet tested on iOS.
This is a real show stopper makes SymbolLayers and therefore the complete Mapbox implementation useless for dynamic content.

Author Feedback Verify on Latest Version upstream

Most helpful comment

@jordan-tpz

After trying several ways to temporary fix this bug, I came up to the conclusion that the best option is to locally update Mapbox SDK to the latest version for both platforms (Android and iOS).

I'm not sure about consequences, but this solution works perfectly for me. If you decide to make this change in your app, then I recommend to run heavy smoke tests on the Mapbox component (just to make sure it didn't break any functionality).

How to locally update Mapbox SDK?
iOS:
https://github.com/react-native-mapbox-gl/maps/blob/master/ios/install.md

Android:
In _android/build.gradle_ in the _allprojects > repositories_ block add the following configuration:

maven {
            url 'https://api.mapbox.com/downloads/v2/releases/maven'
            authentication {
                basic(BasicAuthentication)
            }
            credentials {
                // Do not change the username below.
                // This should always be `mapbox` (not your username).
                username = 'mapbox'
                // Use the secret token you stored in gradle.properties as the password
                password = project.properties['MAPBOX_DOWNLOADS_TOKEN'] ?: ""
            }
        }

and then in _android/app/build.gradle_ in the dependencies block add:

implementation 'com.mapbox.mapboxsdk:mapbox-sdk-services:5.6.0'
implementation 'com.mapbox.mapboxsdk:mapbox-android-sdk:9.5.0'
implementation 'com.mapbox.mapboxsdk:mapbox-android-plugin-annotation-v9:0.9.0'

Clear your gradle cache and then re-build the app.

(for more info visit https://docs.mapbox.com/android/maps/guides/install/)

All 21 comments

Hi @janweigel have you tried adding iconAllowOverlap: true. The attached screenshot looks like the icon is colliding with other elements

@Gnative I tested with both, overlapping true and false.
It doesn't make any difference. There are no other elements it could collide with.

@ferdicus in the native issue you mentioned is a comment that the issue should be resolved at least partially in the native verions 9.3.0 Android and 6.0.0 iOS.
Are there any plans or estimates when react-native-mapbox will be updated to the latest native versions?

hey @janweigel, there is no timeline yet, one thing that was holding us back to publish a new release was the changes in updating the iOS version, which was fixed via 15e75900847046883df09f9da96dbb113a1cbaa8.

We're currently at 8.1.0.rc5, I guess the next step could be to upgrade the android and iOS versions, check for breaking changes and increase/ publish a new version.

Having said that, we're basically just a few people doing this in our spare time... so timing may vary.

Hey @ferdicus, thanks for your feedback and your effort on this project.
It would be great to have the upgrades integrated and that bug fixed.
Right now it is a show stopper and we would have to let mapbox go for our products.

@janweigel on iOS you can use different framework version than the default in 8.1.0.rc5 or later
Plese check:
https://github.com/react-native-mapbox-gl/maps/blob/master/CHANGELOG.md#810rc2
https://github.com/react-native-mapbox-gl/maps/pull/940

Hi @janweigel !

Same for me...
Did you find a workaround to fix this issue ? (while waiting for potential future fix in the next updates)

@janweigel, did you try with an Annotation instead of ShapeSource?
I know, that it is using ShapeSource and SymbolLayer internally as well, however that is how we're using it in our project, and we didn't get any flickering of the icon (Android)

I came into the same issue,when use the example drive the line and create a realtime point move , sometimes, the label and river come flickering when the point move .( ps:I use MapboxGL.Animated.ShapeSource )

Hi,
Always the same issue for me.
It still exists using latest release ? If yes, did you find a temporary hack ?

I came into the same issue,when use the example drive the line and create a realtime point move , sometimes, the label and river come flickering when the point move .( ps:I use MapboxGL.Animated.ShapeSource )

i repalce it with markview but came into another issue ,when markview move few steps it will back to origin location while the camera begin animation (ps: when camera animation duration is 0ms,the issue disappear but the move is ugly)

Hi @lishuo0710,

Thank you for your quickly feedback. I continue to investigate about it.

@ferdicus from what I've seen in the code, Annotation is used internally to display the location of the user. The reason why it's not flickering is that you're passing custom children (in this case a CircleLayer) and SymbolLayer is never used

@VladMatvei Did you find a workaround for this issue by using SymbolLayer ?

@VladMatvei, when I said we in our project, I meant in a personal project:

  const myStyles = {
    iconAllowOverlap: true,
    iconSize: [
      'interpolate',
      ['exponential', 1.5],
      ['zoom'],
      10, 
      0.15,
      16, 
      0.4, 
    ],
    iconImage: require('../images/myImage.png'),
    iconPitchAlignment: 'map',
    iconRotationAlignment: 'viewport',
  };


    <MapboxGL.Annotation
      id="my-Source"
      coordinates={myCoords}
      animated={true}
    >
      <MapboxGL.SymbolLayer
        id="myMarker"
        style={layerStyles}
      />
    </MapboxGL.Annotation>

Something like this

@ferdicus sorry for that. I have the same configuration and icon flickering still occurs.

As @janweigel mentioned, this issue is related to the native library we're using and will be fixed after updating to 9.3.0 for Android and 6.0.0 for iOS.

@jordan-tpz Unfortunately, I didn't. I will post here a workaround or hack if I'll manage to find one.

@jordan-tpz

After trying several ways to temporary fix this bug, I came up to the conclusion that the best option is to locally update Mapbox SDK to the latest version for both platforms (Android and iOS).

I'm not sure about consequences, but this solution works perfectly for me. If you decide to make this change in your app, then I recommend to run heavy smoke tests on the Mapbox component (just to make sure it didn't break any functionality).

How to locally update Mapbox SDK?
iOS:
https://github.com/react-native-mapbox-gl/maps/blob/master/ios/install.md

Android:
In _android/build.gradle_ in the _allprojects > repositories_ block add the following configuration:

maven {
            url 'https://api.mapbox.com/downloads/v2/releases/maven'
            authentication {
                basic(BasicAuthentication)
            }
            credentials {
                // Do not change the username below.
                // This should always be `mapbox` (not your username).
                username = 'mapbox'
                // Use the secret token you stored in gradle.properties as the password
                password = project.properties['MAPBOX_DOWNLOADS_TOKEN'] ?: ""
            }
        }

and then in _android/app/build.gradle_ in the dependencies block add:

implementation 'com.mapbox.mapboxsdk:mapbox-sdk-services:5.6.0'
implementation 'com.mapbox.mapboxsdk:mapbox-android-sdk:9.5.0'
implementation 'com.mapbox.mapboxsdk:mapbox-android-plugin-annotation-v9:0.9.0'

Clear your gradle cache and then re-build the app.

(for more info visit https://docs.mapbox.com/android/maps/guides/install/)

Closing this, as the issue at hand seems to be an upstream issue - which seems solvable by updating the lib SDKs

I was experiencing the flickering in another project now as well.
project without flickering => raster tiles
project with flickering => vector tiles
Not sure if that is the cause, however I thought it's a relevant enough datapoint.

I can verify @VladMatvei solution - an upgrade to a later Android SDK removes the flickering.

I will update the installation this coming friday.

I was experiencing the flickering in another project now as well.
project without flickering => raster tiles
project with flickering => vector tiles
Not sure if that is the cause, however I thought it's a relevant enough datapoint.

I can verify @VladMatvei solution - an upgrade to a later Android SDK removes the flickering.

I will update the installation this coming friday.

@ferdicus I tried to update to the latest Android SDK by following @VladMatvei solution, but this is still an issue for me. For information I use the latest release 8.1.0

Was this page helpful?
0 / 5 - 0 ratings

Related issues

andrei-tofan picture andrei-tofan  Â·  5Comments

jayhaluska picture jayhaluska  Â·  5Comments

gmaclennan picture gmaclennan  Â·  3Comments

alexisrougnant picture alexisrougnant  Â·  3Comments

arnaudambro picture arnaudambro  Â·  5Comments