javascriptjsonmapboxgeojsonmaplibre-gl

Single text label for a MultiLineString in MapLibre GL JS


I'm trying to display text labels for MultiLineString features in a geoJSON file using MapLibre GL JS. I'm using the symbol-placement: point option so I can see the labels on different zoom levels and not just when I get really close as it would happen if I use the line option.

...

map.addSource('source_data', {
        type: 'geojson',
        data: 'sample.geojson'
    });

map.addLayer({
    "id": "symbols",
    "type": "symbol",
    "source": "source_data",
    "layout": {
        "symbol-placement": "point",
        "text-field": '{Name}',
        "text-size": 40,
        "text-justify": "center",
        "text-allow-overlap": false
      }
});

...

The thing is that when the MultiLinestring has more than one line, MapLibre is rendering a label for every one of them as seen in the image below. Is there a way to render only one text label for each MultiLineString feature?

I'm leaving a sample of the geoJSON file I'm using (with the two features of the image) because the original file is really long: https://www.jsonblob.com/1120054652224946176

enter image description here


Solution

  • I would create a new point source for the labels by using turf/center of mass for each feature. This can be used to create a label layer then.

    Installation

    npm install @turf/center-of-mass
    

    import centerOfMass from "@turf/center-of-mass";
    
    const yourGeojson = {}
    const labelPoints = yourGeojson.features.map(feature => centerOfMass(feature, {properties: {Name: feature.properties.Name}}))
    
    map.addSource('labelSource', {'type': 'geojson', 'data': {type: "FeatureCollection", features: labelPoints}})
    
    map.addLayer({
        'id': 'labelLayer',
        'type': 'symbol',
        'source': 'labelSource',
        'layout': {
            'text-field': ['get', 'Name'],
        }
    });