0
votes

I am having difficulty wrapping my head around MapBox GL. I am coming from a Leaflet background, and am finding some of the abstractions hard to understand.

I work with a lot of GPS trip log data, and need to do things like display a fragment of a trip, hilight a section of it in a color, put markers on it with custom pins. Another common function is to mark all units on a map with pins that differ by some status. eg: Last Reported, Fuel Level, etc.

To create markers, I currently have a helper objectthat spits out some js.

public string EmitJs()
{
    Debug.WriteLine("Emit Marker");
    StringBuilder sb = new StringBuilder();
    sb.AppendFormat("var container{0} = document.createElement('div');", UniqueId).AppendLine();
    sb.AppendFormat("container{0}.className = '{1}';", UniqueId, ContainerCss).AppendLine();
    sb.AppendFormat("var popup{0} = new mapboxgl.Popup({{ offset: 25 }}).setHTML(", UniqueId).AppendLine(); // escape { } with {{ }} in String.Format
    sb.AppendFormat("    \'{0}\'", Point.Label).AppendLine();
    sb.AppendLine(");");
    sb.AppendFormat("var marker{0} = new mapboxgl.Marker(container{1}, {{", UniqueId, UniqueId).AppendLine();
    sb.AppendLine("    anchor: 'bottom'");
    sb.AppendLine("})");
    sb.AppendFormat("  .setLngLat({0})", Point.EmitForMapBox()).AppendLine();
    sb.AppendFormat("  .setPopup(popup{0})", UniqueId).AppendLine();
    sb.AppendLine("  .addTo(map);");
    sb.AppendLine();

    return sb.ToString();
}

this returns:

var container5 = document.createElement('div');
container5.className = 'marker marker-pu-green';
var popup5 = new mapboxgl.Popup({ offset: 25 }).setHTML(
    '<p><b>Name:</b> 1310 PU2003<br /><b>Last Reported:</b> 25/03/2020 11:16:35<br /><b>Last Status:</b> Operating</p>'
);
var marker5 = new mapboxgl.Marker(container5, {
    anchor: 'bottom'
})
  .setLngLat([151.047211,-32.537003])
  .setPopup(popup5)
  .addTo(map);

This lets me display images overlaid on a map, governed by CSS. This is fairly straightforward.

The GeoJson FeatureCollection, contains Feature's that represent individual markers. I can see that the icon properties in the Layer object are meant to represent named values in some spritesheet, but damned If I can figure where this is, and how to upload to it. I've been all thru Studio, and its documentation. It seems to refer to to a 'sprites': 'path to file' json property that you can't actually set or upload.

In addition, it wants the sprites to be in SVG format., despite casting them back to raster as PNG. Thats a different question, but I need to convert a bunch of PNG's to SVG format as a result, if I ever get this working.

The Question

How do I add custom sprites to my MapBox style so I can reference them in GeoJson icon properties.

** Edit 27 Mar 202 **

The following is cut from the page. The polylines are not included (they work well), just the lines to try an make a symbol layer work. The image paths are local to my dev environment and are valid. They would be rewritten when moved to prod.

<script id="mapScript" type="text/javascript">
var baseUrl = '/';
mapboxgl.accessToken = '[snip]';
var map = new mapboxgl.Map({
    container: 'map',
    style: 'mapbox://styles/fleetlogixmaps/ck6r4knm10smq1irxvnvfmq1b',
    center: [148.381332397461,-21.4777641296387],
    setMinZoom: 13,
    setMaxZoom: 18,
    zoom: 15,
});



map.loadImage('http://localhost:7933/Images/pin_path_start_128x128.png', function(error, image) {
    if (error) throw error;
    map.addImage('pathStart', image);
});

map.loadImage('http://localhost:7933/Images/pin_path_end_128x128.png', function(error, image) {
    if (error) throw error;
    map.addImage('pathEnd', image);
});

map.loadImage('http://localhost:7933/Images/pin_event_start_128x128.png', function(error, image) {
    if (error) throw error;
    map.addImage('eventStart', image);
});

map.loadImage('http://localhost:7933/Images/pin_event_end_128x128.png', function(error, image) {
    if (error) throw error;
    map.addImage('eventEnd', image);
});

var markers = {
    'type': 'FeatureCollection',
    'features': [
        {
            'type': 'Feature',
            'geometry': {
                'type': 'Point',
                'coordinates': 
                    [148.370483398438,-21.4804000854492],
                'properties': {
                    'title': 'Path Start',
                    'icon': 'pathStart'
                }
            }
        },

        {
            'type': 'Feature',
            'geometry': {
                'type': 'Point',
                'coordinates': 
                    [148.381332397461,-21.4777641296387],
                'properties': {
                    'title': 'Event Start',
                    'icon': 'eventStart'
                }
            }
        },

        {
            'type': 'Feature',
            'geometry': {
                'type': 'Point',
                'coordinates': 
                    [148.385375976563,-21.4819965362549],
                'properties': {
                    'title': 'Event End',
                    'icon': 'eventEnd'
                }
            }
        },

        {
            'type': 'Feature',
            'geometry': {
                'type': 'Point',
                'coordinates': 
                    [148.393402099609,-21.4885864257813],
                'properties': {
                    'title': 'Path End',
                    'icon': 'pathEnd'
                }
            }
        }

    ]
};

map.on('load', function() {
    map.addLayer({
        'id': 'markers',
        'source': 'markerSrc',
        'type': 'symbol',
        'layout': {
            'icon-image': ['get', 'icon'],
            'icon-size': 0.25,
        },


    });

});

</script>
1

1 Answers

0
votes

You're confusing Markers (HTML elements that sit over the map) with Symbol layers (images that exist within the map, tied to a source like a GeoJSON).

Markers don't have anything to do with Sprites: you style them with CSS. See this example.

If you do want to use a Symbol layer, the easiest way to use custom images is to upload them to Mapbox Studio, which will generate the Sprite file for you.

enter image description here

Alternatively, you can use loadImage to load images dynamically.