Skip to content
This repository has been archived by the owner on Aug 8, 2023. It is now read-only.

Dynamic visibility layer property not applied until after moving / scaling map #6758

Closed
ShibaBandit opened this issue Oct 19, 2016 · 8 comments
Assignees
Labels
Android Mapbox Maps SDK for Android

Comments

@ShibaBandit
Copy link

ShibaBandit commented Oct 19, 2016

Platform: Android
Mapbox SDK version: 4.2.0-beta.3

Steps to trigger behavior

Layer layer = map.getLayer("layerId");
layer.setProperties(PropertyFactory.visibility(Property.VISIBLE));

Notes

  • Tried calling invalidate() on MapboxMap and MapView, no effect.
  • Layer changes are being applied on ApplicationContext main loop via a handler.post().
  • A Java Time Thread periodically calls handler.post(), so no map interaction is required for the property change.
  • There are many layers being hidden and shown. We're flipping fill layers to do a radar animation loop.
  • Problem does not occur if I just change opacity using 1f and 0f values instead of VISIBLE or NONE.

Expected behavior

Layers are visible after changing the visibility property to VISIBLE.

Actual behavior

Layers only become visible after changing the visibility property to VISIBLE AND moving the map (drag / zoom).

@ShibaBandit ShibaBandit changed the title Dyanamic visibility layer property not applied until after moving / scaling map Dynamic visibility layer property not applied until after moving / scaling map Oct 19, 2016
@tobrun tobrun added the Android Mapbox Maps SDK for Android label Oct 20, 2016
@ivovandongen ivovandongen self-assigned this Oct 20, 2016
@ivovandongen
Copy link
Contributor

ivovandongen commented Oct 20, 2016

@ShibaBandit There is a test case for this in the testapp. Just tested on master, works as expected.

I also changed the activity so that it's triggered by a timer (see diff). This also works as expected.

Could you try the latest snapshot and see if your problem persists? If it does, please re-open the ticket with a minimal case to reproduce.

@ShibaBandit
Copy link
Author

Thank you, latest snapshot does not have this problem.

I do notice that drawing the new layer flickers in though, rather than allowing an instantaneous transition like opacity changes.

@cammace
Copy link
Contributor

cammace commented Oct 24, 2016

Could you clarify what the issue you are experiencing with the latest SNAPSHOT looks like? I added a FillLayer to the map and toggled the visibility on/off when the maps clicked with no resulting flickering. Any additional information would help troubleshoot the issue including code or videos/gifs.

ezgif com-video-to-gif 2

@ShibaBandit
Copy link
Author

Sorry for long response time, was out of the office. Re-cap: Snapshot build fixed having to move the map to have visible layers be displayed. However, flickering persists if I don't prepare the next frame as a 0-opacity visible frame. A frame is aprox 40 fill layers of stacked polygons, there are 12 frames and each frame is it's own vector tile source. Essentially flipping tile set visibility over time and wrapping around to the start like you commonly see on a weather app.

Device is Samsung Galaxy S7.

Swapping VISIBLE/NONE:
visible_swap

Swapping Opacity:
opacity_swap

Code:

public void hide(MapboxMap map) {
    for(String layerId : layerIds) {
        Layer layer = map.getLayer(layerId);
        if(layer != null) {
            if(Property.VISIBLE.equals(layer.getVisibility().getValue())) {
                layer.setProperties(PropertyFactory.visibility(Property.NONE));
            }
        }
    }
}

public void show(MapboxMap map) {
    for(String layerId : layerIds) {
        Layer layer = map.getLayer(layerId);
        if(layer != null) {
            if(Property.NONE.equals(layer.getVisibility().getValue())) {
                layer.setProperties(PropertyFactory.visibility(Property.VISIBLE));
            }
        }
    }
}

Please let me know if you need me to post the code base, I can look into getting that public.

@ivovandongen
Copy link
Contributor

@ShibaBandit I think you're on the right track with using opacity instead of visibility here. When changing visibility we reload the underlying source and re-layout everything (as an optimisation so that sources with only invisible layers are not even loaded). On opacity changes a more simple repaint is done. In your case, you have a lot of layers (and possibly sources) to update which might just be too much of a strain on your device.

May I ask what your sources look like? Are you using a single source with filters? Or a source per layer/frame? I'm trying to reproduce this locally to see where the bottleneck is.

@ShibaBandit
Copy link
Author

ShibaBandit commented Nov 2, 2016

The GIFs above use:

  • total of 12 sources (per layer/frame), where each source is a radar mosaic time.
  • Each source has ~30-40 stacked polygons (Fill Layers). The Fill layers select one of the polygons by attribute "dbz" from a "reflectivity" MVT layer. So there's roughly 30-40 Fill Layers each selecting a "dbz" range and associating that with a color.
  • All styling is dynamically generated and added on top of a default Mapbox basemap.

The current work-around I am using is to prepare the next frame as a 0-opacity visible frame and hide others.

Example code for dynamic styling, called for each radar source (12) on app start():

public static MapFrame createMapFrame(MapboxMap mapboxMap, String host, String port, Meta fm) {
    final String frameUuid = fm.uuid;
    final String sourceId = "src-" + fm.validTime;
    final String layerId = "layer-" + fm.validTime;

    final TileSet tileSet = new TileSet(
            "2.1.0",
            "http://" + host + ":" + port + "/v2/frames/" + frameUuid + "/tile/{z}/{x}/{y}.mvt");

    final Source source = new VectorSource(sourceId, tileSet);
    mapboxMap.addSource(source);


    final List<String> layerIds = new ArrayList<>(ColorStep.DEFAULT_COLOR_STEPS.size());

    for(ColorStep s : ColorStep.DEFAULT_COLOR_STEPS) {
        String nextLayerId = layerId + s.max + "," + s.min;
        layerIds.add(nextLayerId);

        final FillLayer layer = new FillLayer(nextLayerId, sourceId);
        layer.setSourceLayer("reflectivity");
        layer.setFilter(
                Filter.all(
                        Filter.gt("dbz", s.min),
                        Filter.lte("dbz", s.max)
                )
        );
        layer.setProperties(
                PropertyFactory.fillColor(s.rgbaColor),
                PropertyFactory.fillOpacity(DEFAULT_OPACITY),
                PropertyFactory.fillAntialias(true)
        );
        mapboxMap.addLayer(layer);
    }

    return new MapFrame(fm, sourceId, layerIds);
}

@ShibaBandit
Copy link
Author

@ivovandongen I have the example code at https://github.com/wdtinc/skywise_mb_android_example if you're interested still.

Temporary USERNAME / PASSWORD:
2b5953aa / 40c2b5c9813acd0144b2162a13c9a193

I'll leave this account around for a bit if you're interested in and delete it in a month or so.

@ivovandongen
Copy link
Contributor

@ShibaBandit I'm working on this in #7241.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Android Mapbox Maps SDK for Android
Projects
None yet
Development

No branches or pull requests

4 participants