rnmapbox / maps

A Mapbox react native module for creating custom maps
MIT License
2.27k stars 848 forks source link

[Bug]: SymbolLayer not rendering icons correctly #2941

Closed wmonecke closed 1 year ago

wmonecke commented 1 year ago

Mapbox Implementation

Mapbox

Mapbox Version

default

Platform

iOS, Android

@rnmapbox/maps version

10.0.4-rc.0

Standalone component to reproduce

import React from 'react';
import MapboxGL, {
  MapView,
  ShapeSource,
  LineLayer,
  Camera,
} from '@rnmapbox/maps';

const MarkerIds = [
  'onRamp',
  'roadClosure',
  'animalShelter',
  'resourceCenter',
  'evacuationCenter',
  'trafficControlPoint',
]

const mapPointsOfInterestToLayerNumberId = {
  ['evacuationCenter']: 2,
  ['animalShelter']: 3,
  ['resourceCenter']: 4,
  ['roadClosure']: 8,
  ['trafficControlPoint']: 7,
  ['onRamp']: 1,
} 

const data = {
    "bbox":[
        -3.7054,
        40.4178,
        -3.7029,
        40.4275
    ],
    "features":[
        {
            "type":"Feature",
            "id":"arrival_point.7986",
            "geometry":{
                "type":"Point",
                "coordinates":[
                    -3.7054,
                    40.4275
                ]
            },
            "geometry_name":"geom",
            "properties":{
                "arrival_point_id":7986,
                "arrival_point_name":"Test",
                "arrival_point_address":"Calle De Monteleón 6, 28004 Madrid, Madrid, Spain",
                "arrival_point_type":2
            },
            "bbox":[
                -3.7054,
                40.4275,
                -3.7054,
                40.4275
            ]
        },
        {
            "type":"Feature",
            "id":"arrival_point.7987",
            "geometry":{
                "type":"Point",
                "coordinates":[
                    -3.7029,
                    40.4178
                ]
            },
            "geometry_name":"geom",
            "properties":{
                "arrival_point_id":7987,
                "arrival_point_name":"Test Animal Shelter",
                "arrival_point_address":"Calle De La Montera 13, 28013 Madrid, Madrid, Spain",
                "arrival_point_type":3
            },
            "bbox":[
                -3.7029,
                40.4178,
                -3.7029,
                40.4178
            ]
        },
        {
            "type":"Feature",
            "id":"zone_traffic_control_point.fid-3fd214df_1891fa999aa_40b0",
            "geometry":{
                "type":"Point",
                "coordinates":[
                    -3.7307,
                    40.4277
                ]
            },
            "geometry_name":"geom",
            "properties":{
                "id":10464,
                "tcp_name":"Test Road Closure",
                "tcp_type":"roadClosure",
                "tcp_rank":1,
                "tcp_note":"{\"blocks\": [{\"key\": \"tt78\", \"text\": \"Lorem ipsum dolor sit amet. Rich text formatting can help bring the idea over more efficiently.\", \"type\": \"unstyled\", \"depth\": 0, \"inlineStyleRanges\": [{\"offset\": 22, \"length\": 4, \"style\": \"STRIKETHROUGH\"}, {\"offset\": 28, \"length\": 20, \"style\": \"BOLD\"}, {\"offset\": 83, \"length\": 11, \"style\": \"ITALIC\"}], \"entityRanges\": [], \"data\": {}}], \"entityMap\": {}}",
                "arrival_point_type":8
            },
            "bbox":[
                -3.7307,
                40.4277,
                -3.7307,
                40.4277
            ]
        },
        {
            "type":"Feature",
            "id":"zone_traffic_control_point.fid-3fd214df_1891fa999aa_40b1",
            "geometry":{
                "type":"Point",
                "coordinates":[
                    -3.702,
                    40.425
                ]
            },
            "geometry_name":"geom",
            "properties":{
                "id":10467,
                "tcp_name":"test TCP",
                "tcp_type":"trafficControlPoint",
                "tcp_rank":2,
                "tcp_note":null,
                "arrival_point_type":7
            },
            "bbox":[
                -3.702,
                40.425,
                -3.702,
                40.425
            ]
        },
        {
            "type":"Feature",
            "id":"zone_traffic_control_point.fid-3fd214df_1891fa999aa_40b2",
            "geometry":{
                "type":"Point",
                "coordinates":[
                    -3.6984,
                    40.427
                ]
            },
            "geometry_name":"geom",
            "properties":{
                "id":10466,
                "tcp_name":"Test TCP",
                "tcp_type":"roadClosure",
                "tcp_rank":2,
                "tcp_note":null,
                "arrival_point_type":8
            },
            "bbox":[
                -3.6984,
                40.427,
                -3.6984,
                40.427
            ]
        },
        {
            "type":"Feature",
            "id":"zone_traffic_control_point.fid-3fd214df_1891fa999aa_40b3",
            "geometry":{
                "type":"Point",
                "coordinates":[
                    -3.6988,
                    40.4347
                ]
            },
            "geometry_name":"geom",
            "properties":{
                "id":11359,
                "tcp_name":"Test Road Closureeee",
                "tcp_type":"roadClosure",
                "tcp_rank":1,
                "tcp_note":"{\"blocks\":[{\"key\":\"e8aif\",\"text\":\"This is a test road closure!\",\"type\":\"unstyled\",\"depth\":0,\"inlineStyleRanges\":[],\"entityRanges\":[],\"data\":{}}],\"entityMap\":{}}",
                "arrival_point_type":8
            },
            "bbox":[
                -3.6988,
                40.4347,
                -3.6988,
                40.4347
            ]
        },
        {
            "type":"Feature",
            "id":"zone_traffic_control_point.fid-3fd214df_1891fa999aa_40b4",
            "geometry":{
                "type":"Point",
                "coordinates":[
                    -3.6902,
                    40.4284
                ]
            },
            "geometry_name":"geom",
            "properties":{
                "id":11360,
                "tcp_name":"Test TCPPP",
                "tcp_type":"trafficControlPoint",
                "tcp_rank":1,
                "tcp_note":null,
                "arrival_point_type":7
            },
            "bbox":[
                -3.6902,
                40.4284,
                -3.6902,
                40.4284
            ]
        },
        {
            "type":"Feature",
            "id":"zone_traffic_control_point.fid-3fd214df_1891fa999aa_40b5",
            "geometry":{
                "type":"Point",
                "coordinates":[
                    -3.6916,
                    40.4437
                ]
            },
            "geometry_name":"geom",
            "properties":{
                "id":11392,
                "tcp_name":"TEST TCP",
                "tcp_type":"trafficControlPoint",
                "tcp_rank":1,
                "tcp_note":"{\"blocks\":[{\"key\":\"ccvlc\",\"text\":\"This should hopefully work\",\"type\":\"unstyled\",\"depth\":0,\"inlineStyleRanges\":[],\"entityRanges\":[],\"data\":{}}],\"entityMap\":{}}",
                "arrival_point_type":7
            },
            "bbox":[
                -3.6916,
                40.4437,
                -3.6916,
                40.4437
            ]
        }
    ],
    "type":"FeatureCollection"
}

class BugReportExample extends React.Component {
  render() {
    return (
      <MapView style={{flex: 1}}>
          <Camera centerCoordinate={[-3.6916, 40.4437]} zoomLevel={14} />

          <MapboxGL.Images
            images={{
              roadClosure: '../assets/example.png',
              evacuationCenter: '../assets/example.png',
              animalShelter:  '../assets/example.png',
              trafficControlPoint:  '../assets/example.png',
              fireIcon:  '../assets/example.png',
            }}
          />

       <MapboxGL.ShapeSource
      id="markers"
      shape={data}
    >
      {MarkerIds.map((id) => {
        const layerNumber = mapPointsOfInterestToLayerNumberId[`${id}`];

        return (
          <MapboxGL.SymbolLayer
            key={id}
            aboveLayerID="evacuation_zone"
            id={id}
            style={{
              iconSize: [
                'interpolate',
                ['linear'],
                ['zoom'],
                8,
                0,
                12,
                0.3,
                14,
                0.5,
                15,
                0.65,
              ],
              iconImage: id,
              textAllowOverlap: true,
              iconAllowOverlap: true,
            }}
            sourceID="markers"
            filter={['==', 'arrival_point_type', layerNumber]}  // this filter is removing some of the icons that should be showing
            sourceLayerID="markers"
          />
        );
      })}
    </MapboxGL.ShapeSource>
      </MapView>
    );
  }
}

Observed behavior and steps to reproduce

Currently not all icons in the data are being rendered. We have the same logic in web an we are able to render all markers.

On mobile the data is present and as soon as we remove the filter the icons show up, albeit with the wrong icon.

Expected behavior

The right icons to be rendered.

Notes / preliminary analysis

In the video, you will see that there are 5 icons rendered with their corresponding icon.

After removing the filter and reloading the simulator you can see that 8 icons are rendered on the screen however without the correct icon. This means that somehow the filter is removing additional icons. You can see the data returned by our API in the code above.

Additional links and references

https://github.com/rnmapbox/maps/assets/24256469/2c805256-8f3b-45b7-b74d-74b2172375ac

mfazekas commented 1 year ago

@wmonecke thank much for the report. However when running it I'm getting error. Pls fix, so I can try to reproduce the issue, thanks.

image

wmonecke commented 1 year ago

@mfazekas Any ideas on what could be breaking? If I run this locally it is working for me (as you can see in the video).

mfazekas commented 1 year ago

I’ve tried on android. Some layerNumber values were undefined

wmonecke commented 1 year ago

@mfazekas Could we plz reopen this issue? The code has been updated and the issue is still present even after debugging this for 3 days straight. The code is working as expected on web.

mfazekas commented 1 year ago

@wmonecke sorry I still don't understand the bug report. I see this on android emulator:

image

I'm not sure what's should be I seeing or what's wrong here. Please be specific. Also updated linter so require('../assets/example.png') should be allowed now.

wmonecke commented 1 year ago

@mfazekas You should be seeing the markers on the map (all the small red and green round ones that appear in the video above).

Did you zoom out a bit?

As you can see in the video not all markers are being rendered on screen. You will be seeing 5 icons but if you check the data variable it contains the data for 8 markers.

I hope this clarifies things a bit better. Updated the code with ../assets/example.png

mfazekas commented 1 year ago

@wmonecke pls place and image under ../assets/example.png, please get the same example snippet you're reporting here working in your app. Because this component will not render anything for you as well I'm sure. Even better if you repro the issue in our example app as well.

I'm sorry but we have very limited resources, and we don't provide free support.

Also please verify on latest versions.

Dru1X commented 1 year ago

I'm not sure if it's entirely related, but I've experienced issues with SymbolLayers not displaying correctly when the associated feature has a property with a value of null. From the data @wmonecke provided, there are some features that fit this description. Perhaps try removing any keys with null values, or replace null with an empty string.

wmonecke commented 1 year ago

@Dru1X This was it! Thank you very much.

@mfazekas FYI. If any properties has null as its value it will not be rendered. This a discrepancy with web.

mfazekas commented 1 year ago

@wmonecke This should have been fixed in 10.13+ version of native libs: https://github.com/mapbox/mapbox-maps-ios/blob/cf286de094c7bd413697ab67da0d5866f790009e/CHANGELOG.md?plain=1#L46