Map Customization

Add custom map layers, tiles, and styles

The map API lets you add custom tile sources, layers, and styles to the game map.

Add Custom Tile Source#

javascript
window.SubwayBuilderAPI.map.registerSource('custom-tiles', {
    type: 'raster',
    tiles: ['https://tile.server.com/{z}/{x}/{y}.png'],
    tileSize: 256
});

Add Custom Map Layer#

javascript
window.SubwayBuilderAPI.map.registerLayer({
    id: 'custom-layer',
    type: 'fill',
    source: 'custom-tiles',
    paint: {
        'fill-color': '#088',
        'fill-opacity': 0.5
    }
});

Add Custom MapLibre Style#

javascript
window.SubwayBuilderAPI.map.registerStyle('https://demotiles.maplibre.org/style.json');

Override Tile URLs#

For custom cities with localhost tiles:

javascript
window.SubwayBuilderAPI.map.setTileURLOverride({
    cityCode: 'MTL',
    tilesUrl: 'http://127.0.0.1:8080/MTL/{z}/{x}/{y}.mvt',
    foundationTilesUrl: 'http://127.0.0.1:8080/MTL/{z}/{x}/{y}.mvt',
    maxZoom: 15
});

Override Layer Properties#

Customize layer source-layers or properties for custom tiles:

javascript
// Parks layer uses different source-layer
window.SubwayBuilderAPI.map.setLayerOverride({
    layerId: 'parks-large',
    sourceLayer: 'landuse',
    filter: ['==', ['get', 'kind'], 'park']
});

// Airports layer
window.SubwayBuilderAPI.map.setLayerOverride({
    layerId: 'airports',
    sourceLayer: 'landuse',
    filter: ['==', ['get', 'kind'], 'aerodrome']
});

// Water layer height adjustment
window.SubwayBuilderAPI.map.setLayerOverride({
    layerId: 'water',
    paint: {
        'fill-extrusion-height': 0.1
    }
});

Set Default Layer Visibility#

Disable layers by default for cities without certain data:

javascript
window.SubwayBuilderAPI.map.setDefaultLayerVisibility('MTL', {
    buildingFoundations: false,
    oceanFoundations: false,
    trackElevations: false
});

Available layers:

  • buildingFoundations - Building foundation depth visualization
  • oceanFoundations - Ocean depth visualization
  • trackElevations - Track elevation labels
  • trains, stations, routes, arrows, signals, etc.

Routing Service Override#

For custom city data generation, you can register a routing service:

javascript
window.SubwayBuilderAPI.map.setRoutingServiceOverride({
    cityCode: 'MTL',
    routingUrl: 'http://localhost:5000/route/v1/driving/{origin_lon},{origin_lat};{dest_lon},{dest_lat}?overview=full&geometries=geojson',
    format: 'osrm' // 'osrm' | 'valhalla' | 'graphhopper' | 'custom'
});

// Query routes
const result = await window.SubwayBuilderAPI.map.queryRoute(
    'MTL',
    [-73.5673, 45.5017], // origin [lon, lat]
    [-73.5500, 45.5200]  // destination [lon, lat]
);

if (result) {
    console.log('Driving time:', result.drivingSeconds, 'seconds');
    console.log('Distance:', result.drivingDistance, 'meters');
}

Supported formats:

FormatDescription
osrmOSRM routing service
valhallaValhalla routing service
graphhopperGraphHopper routing service
customCustom parser (provide customParser function)

Custom Parser#

javascript
window.SubwayBuilderAPI.map.setRoutingServiceOverride({
    cityCode: 'MTL',
    routingUrl: 'http://localhost:3000/api/route?from={origin_lon},{origin_lat}&to={dest_lon},{dest_lat}',
    format: 'custom',
    customParser: (response) => ({
        drivingSeconds: response.time_sec,
        drivingDistance: response.dist_m,
        drivingPath: response.coords // optional
    })
});

Get Map Instance#

Access the raw MapLibre map instance:

javascript
const map = window.SubwayBuilderAPI.utils.getMap();
if (map) {
    map.setZoom(15);
    map.on('click', (e) => {
        console.log('Clicked:', e.lngLat);
    });
}

Map Ready Hook#

Wait for map to be ready before accessing it:

javascript
window.SubwayBuilderAPI.hooks.onMapReady((map) => {
    console.log('Map is ready!');

    // Add custom click handler
    map.on('click', (e) => {
        const { lng, lat } = e.lngLat;
        console.log(`Clicked at ${lat}, ${lng}`);
    });

    // Add custom layer
    map.addLayer({
        id: 'my-highlight-layer',
        type: 'circle',
        source: {
            type: 'geojson',
            data: {
                type: 'FeatureCollection',
                features: []
            }
        },
        paint: {
            'circle-radius': 10,
            'circle-color': '#ff0000'
        }
    });
});

Example: Custom Basemap#

javascript
// Add OpenStreetMap as basemap
window.SubwayBuilderAPI.map.registerSource('osm-tiles', {
    type: 'raster',
    tiles: ['https://tile.openstreetmap.org/{z}/{x}/{y}.png'],
    tileSize: 256,
    attribution: '© OpenStreetMap contributors'
});

window.SubwayBuilderAPI.map.registerLayer({
    id: 'osm-basemap',
    type: 'raster',
    source: 'osm-tiles'
});