React-native-mapbox-gl: annotation vs SymbolLayer

Created on 29 Nov 2017  路  22Comments  路  Source: nitaliano/react-native-mapbox-gl

Hello,
According to the doc
javascript/components/SymbolLayer.js
SymbolLayer is a style layer that renders icon and text labels at points or along lines on the map.
javascript/components/PointAnnotation.js
PointAnnotation represents a one-dimensional shape located at a single geographical coordinate.
I want to have the most bestpractice as possible to show multiple custom markers with callout
in the example one is not use with the other.
Here's my code :

<MapboxGL.MapView
                    ref={(ref) => this.map = ref}
                    style={{height: 600}}
                    zoomLevel={this.state.zoom}
                    showUserLocation={this.state.isAndroidPermissionGranted}
                    userTrackingMode={MapboxGL.UserTrackingModes.Follow}
                    centerCoordinate={SF_OFFICE_COORDINATE}
                    minimumZoomLevel={3}
                    maximumZoomLevel={15}
                    attributionEnabled={false}
                    logoEnabled={false}
                    debugActive
                >
        <MapboxGL.ShapeSource
                    id='symbolLocationSource'
                    shape={this.state.featureCollection}
                    cluster
                    clusterMaxZoomLevel={10}

        >
            <MapboxGL.SymbolLayer
                        id='symbolLocationSymbols'
                        minZoomLevel={10}
            >
                    </MapboxGL.SymbolLayer>
                    </MapboxGL.ShapeSource>

                </MapboxGL.MapView>

this.state.featureCollection is a geoJSON, with points and it shows nothing, but annotations with no layer works but doesn't look great to me.
What is a layer in general and what is his purpose?
What is better to do?
Jessica

Most helpful comment

PointAnnotation(Annotation Views) are a legacy concept. It comes from the web where you can add say a View(div) on the screen and be able to add touch events, animate elements, and styling them using your frameworks styling API. The problem is these type of annotations do not scale, they need to be synchronized with the map every time you move the map causing a shake, if you try to animate one of these the CPU increases, you just cannot have millions of them on screen.

Layers are not Views they are actually added to your vector tiles which gives you insane performance gains, you can literally have thousands of points on screen with ease, clustering support, and ability to style it however you want. Another perk is that our c++ codebase is handling all of this so you get very consistent results cross platforms.

More and more support for things like callouts are going to be added to layers, we recently introduced an onPress to Vector and Shape sources. There will also be Annotation components built on top of layers in the coming months. The only reason we added Annotation Views to this SDK is we have users that are already using Annotation Views from the v5 branch and we didn't want to make the migration too painful, but we will deprecate PointAnnotations in the future in favor of a Layer based Annotation component.

All 22 comments

Edit: I tried it, and I think I know the difference.

I think that nothing shows because you don't define a style to your SymbolLayer.
You need to modify your symbolLayer like this:

<MapboxGL.SymbolLayer
    id='symbolLocationSymbols'
    minZoomLevel={10}
    style={style.symbol}
>

Your style.symbol can contain anything from here, both layout and paint properties that you usually have in your layers (but names are names looks like 'iconSize' instead of the usual 'icon-size'). For example you can have something like this:

import icon from './images/symbol.png'
const style = Mapbox.StyleSheet.create({
   symbol: {
      iconImage: icon,
      iconSize: 1,
      iconOffset: [0, -32],
      iconAllowOverlap : true
   }
});

I tried annotations and from what I understand: annotation are react components that are placed on top of the map view and moved along when the map moves.

This means that its "easier" to detect interaction with annotations, but when you pan/zoom the map their position (coordinates on the map) may vary (slightly). On the other hand, when you use layers (like the symbol layer) the markers position perfectly fits the map when you pan/zoom but its a bit more costly to detect click on them as you have to call queryRenderedFeaturesAtPoint and it seems that this function performances are not exactly as good as the ones used to detect clicks in react. There is a tradeoff here, I don't really have the number so I can't really tell whats best.

If you want the best of the two, you can have visible markers on a layer, with invisible annotations on top of them. By doing this you have markers that updates nicely when the map moves and you can detect click on them via the annotations. The fact that annotation views have opacity:0 doesn't seem to be a problem and clicks are detected correctly.

That's not exactly the best thing to do as you have to update the two things every time you change your state, but it seems decent enough to me. Moreover you will have to take care about possible offsets that you may have on your symbol layer and update margins on your views (the ones inside the map annotations).

We should wait a real answer from someone from mapbox though 馃槂

from my understanding, annotations are allowed to a maximum of 60 of height, so limited amount of information

It doesn't seem like there is such a limitation, I can display huge annotation with my version.

@cglacet I'd love to have a look to one of your annotation as I spend my day failed to do so

I was actually wrong on something: Layers are not real layers (not like they are when you declare new layers in your mapbox style), and therefore they also suffer from lags when moving the map. Therefore I have no idea why you should chose layers instead of symbols 馃槥.

The best way to do things would be do declare a new layer in your mapbox style file (statically). And then dynamically modify its source content (but I don't know how this can be done with the react version).

You can found one example of annotation here 馃槃

thx @cglacet i knew this one but these dimensions are below mine

I'm not sure to understand what you mean, but you can change the annotation size by modifying ANNOTATION_SIZE which is used in the stylesheet to adjust the annotation's inner view.

ANNotationSize height is below 60 which I think is the average maximum I can get, but I'm working on it...

excuse me it is the size of the callout I'm talking about

This should work: <MapboxGL.Callout title={title} style={{height:500, width:500}}/>. You also can define the style outside if you want it to be clean.

I started my callOut from scratch and it work out, my bad, thank you very much

but i still wander the differences between annotation vs SymbolLayer

PointAnnotation(Annotation Views) are a legacy concept. It comes from the web where you can add say a View(div) on the screen and be able to add touch events, animate elements, and styling them using your frameworks styling API. The problem is these type of annotations do not scale, they need to be synchronized with the map every time you move the map causing a shake, if you try to animate one of these the CPU increases, you just cannot have millions of them on screen.

Layers are not Views they are actually added to your vector tiles which gives you insane performance gains, you can literally have thousands of points on screen with ease, clustering support, and ability to style it however you want. Another perk is that our c++ codebase is handling all of this so you get very consistent results cross platforms.

More and more support for things like callouts are going to be added to layers, we recently introduced an onPress to Vector and Shape sources. There will also be Annotation components built on top of layers in the coming months. The only reason we added Annotation Views to this SDK is we have users that are already using Annotation Views from the v5 branch and we didn't want to make the migration too painful, but we will deprecate PointAnnotations in the future in favor of a Layer based Annotation component.

Thank you very much @nitaliano for these thorough explanation.

till, the new feature comes up what's best to do? @nitaliano

@GuillotJessica I would highly recommend using Sources and Layers. You'll be able to recreate callouts using a Symbol layer and offsets

thx @nitaliano is there one symbol layers per annotation or one for all?

There's one layer that renders whatever is in it's source, so if you have 1 million points in a feature collection only 1 layer instance is created and that renders all of those points into the vector tile.

Checkout this PR to see some screens of new examples to see what layers can do https://github.com/mapbox/react-native-mapbox-gl/pull/846

we recently introduced an onPress to Vector and Shape sources

Does onPress give me context to which specific feature was pressed or just what Shape source received the press? In other words, if a feature from a feature collection was pressed will I know which one, or will I only know what Shape source was pressed?

@iamjaredwalters yes you get the actual feature.

onShapeSourceLayer (e)  {
  const feature = e.nativeEvent.payload;
}

Hello! We have implemented MapboxGL.ShapeSource with MapboxGL.SymbolLayer, however, we are facing one issue.. If I press on PointAnnotation it would fire onPress right away, however, if I press on ShapeSource it would fire onPress only after 1.5 seconds. Can you please advise on this matter? Thanks!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

glennverschooren picture glennverschooren  路  4Comments

max-prokopenko picture max-prokopenko  路  4Comments

madroneropaulo picture madroneropaulo  路  4Comments

VentsislavDinev picture VentsislavDinev  路  3Comments

Maxence-Machu picture Maxence-Machu  路  3Comments