javascriptmaptiler

Maptiler not recognizing custom map ID in style switcher


In the demo here, I am working on a Maptiler map utilizing two default map types and two custom map types in a style switcher and one layer. The code is supposed to switch between styles while reloading the geojson layer at each style change. It works great with the default map styles but not with the custom types. The custom types will not load at all. Typos have been checked and custom styles are published and working in different examples.

<select class="mapstyles-select">
    <option value="e8a7d286-0cf1-4165-bac7-7b1854bb30a0" selected>Natural</option>
    <option value="75422893-dc2f-40fe-af5b-fd89c0ea92d3">Light</option>
    <option value="SATELLITE">Satellite</option>
    <option value="TOPO">Topo</option>
  </select>
  
    maptilersdk.config.apiKey = 'MY API KEY';
    const map = new maptilersdk.Map({
      container: 'map', // container id
      style: "e8a7d286-0cf1-4165-bac7-7b1854bb30a0",
      center: [100.507, 13.7231], // starting position [lng, lat]
      zoom: 10, // starting zoom
    });
    document.querySelector('.mapstyles-select').addEventListener('change', (e) => {
      const style_code = e.target.value.split(".");
      console.log(style_code)
      map.setStyle(maptilersdk.MapStyle[style_code[0]][style_code[0]], {
                  transformStyle: (previousStyle, nextStyle) => {
                    var custom_layers = previousStyle.layers.filter((layer) => {
                      console.log(layer.source)
                      if (layer.source) {
                        return (
                          layer.source.startsWith('my-polygon')
                        );
                      }
                    });

                    var layers = nextStyle.layers.concat(custom_layers);
                    var sources = nextStyle.sources;
                    for (const [key, value] of Object.entries(previousStyle.sources)) {
                      if (key.startsWith('my-polygon')) {
                        sources[key] = value;
                      }
                    }

                    return {
                      ...nextStyle,
                      sources: sources,
                      layers: layers,
                    };
                  }
                });
    });
    
    map.on('load', () => {
          map.addSource('my-polygon', {
            'type': 'geojson',
            'data': {
              'type': 'Feature',
              'properties': {},
              'geometry': {
                'coordinates': [
                  [
                    [
                      100.53964892087583,
                      13.660619302818347
                    ]
                ]
                ]
                'type': 'Polygon'
              }
            }
          });
          map.addLayer({
            'id': 'my-polygon',
            'type': 'fill',
            'source': 'my-polygon',
            'layout': {},
            'paint': {
              'fill-color': '#FF0000',
              'fill-opacity': 0.5
            }
          });
        });

I've tried using my custom map ID's name, i.e., "myTopo", and tried using single quotes instead of double but I don't know why it's not working. My custom maps are working here, but the layer doesn't persist to the other styles. Here's that version's pertinent code:

<select class="mapstyles-select">
    <option value="e8a7d286-0cf1-4165-bac7-7b1854bb30a0" selected>Natural</option>
    <option value="75422893-dc2f-40fe-af5b-fd89c0ea92d3">Light</option>
    <option value="SATELLITE">Satellite</option>
    <option value="TOPO">Topo</option>
  </select>
  
    maptilersdk.config.apiKey = 'MY API KEY';
    const map = new maptilersdk.Map({
      container: 'map', // container id
      style: "e8a7d286-0cf1-4165-bac7-7b1854bb30a0",
      center: [100.507, 13.7231], // starting position [lng, lat]
      zoom: 10, // starting zoom
    });
    document.querySelector('.mapstyles-select').addEventListener('change', (e) => {
      const style_code = e.target.value.split(".");
        map.setStyle(maptilersdk.MapStyle[style_code[0]] || style_code[0]);
    });
    
    map.on('load', () => {
          map.addSource('my-polygon', {
            'type': 'geojson',
            'data': {
              'type': 'Feature',
              'properties': {},
              'geometry': {
                'coordinates': [
                  [
                    [
                      100.53964892087583,
                      13.660619302818347
                    ]`
                  ]
                ],
                'type': 'Polygon'
              }
            }
          });
          map.addLayer({
            'id': 'my-polygon',
            'type': 'fill',
            'source': 'my-polygon',
            'layout': {},
            'paint': {
              'fill-color': '#FF0000',
              'fill-opacity': 0.5
            }
          });
        });


Ideally, I would be able to use custom map styles and default map styles with whatever layers and have those layers persist across styles. In both code examples I abbreviated the geojson.

Solution

  • <!DOCTYPE html>
    <html>
    <head>
      <meta charset="utf-8" />
      <title>Display a map</title>
      <meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" />
      <script src="https://cdn.maptiler.com/maptiler-sdk-js/v2.0.3/maptiler-sdk.umd.js"></script>
      <link href="https://cdn.maptiler.com/maptiler-sdk-js/v2.0.3/maptiler-sdk.css" rel="stylesheet" />
      <style>
        body {
          margin: 0;
          padding: 0;
        }
    
        #map {
          position: absolute;
          top: 0;
          bottom: 0;
          width: 100%;
        }
    
        .mapstyles-select {
          position: absolute;
          top: 10px;
          left: 10px;
          z-index: 1000;
          background: white;
          padding: 5px;
          border-radius: 3px;
        }
      </style>
    </head>
    
    <body>
      <div id="map"></div>
      <select class="mapstyles-select">
        <option value="e8a7d286-0cf1-4165-bac7-7b1854bb30a0" selected>Natural</option>
        <option value="75422893-dc2f-40fe-af5b-fd89c0ea92d3">Light</option>
        <option value="satellite">SATELLITE</option>
        <option value="topo-v2">Topo</option>
      </select>
      <script>
        maptilersdk.config.apiKey = 'your key';
        const map = new maptilersdk.Map({
          container: 'map', // container id
          style: "https://api.maptiler.com/maps/e8a7d286-0cf1-4165-bac7-7b1854bb30a0/style.json?key=your key",
          center: [100.507, 13.7231], // starting position [lng, lat]
          zoom: 10, // starting zoom
        });
    
        const addCustomLayer = () => {
          if (!map.getSource('my-polygon')) {
            map.addSource('my-polygon', {
              'type': 'geojson',
              'data': {
                'type': 'Feature',
                'properties': {},
                'geometry': {
                  'type': 'Polygon',
                  'coordinates': [
                    [
                      [100.507, 13.7231],
                      [100.517, 13.7331],
                      [100.497, 13.7331],
                      [100.507, 13.7231]
                    ]
                  ]
                }
              }
            });
          }
    
          if (!map.getLayer('my-polygon')) {
            map.addLayer({
              'id': 'my-polygon',
              'type': 'fill',
              'source': 'my-polygon',
              'layout': {},
              'paint': {
                'fill-color': '#FF0000',
                'fill-opacity': 0.5
              }
            });
          }
        };
    
        document.querySelector('.mapstyles-select').addEventListener('change', (e) => {
          const styleCode = e.target.value;
          map.setStyle(`https://api.maptiler.com/maps/${styleCode}/style.json?key=${maptilersdk.config.apiKey}`, {
            transformStyle: (previousStyle, nextStyle) => {
              const customLayers = previousStyle.layers.filter((layer) => {
                return layer.source && layer.source.startsWith('my-polygon');
              });
    
              const layers = nextStyle.layers.concat(customLayers);
              const sources = { ...nextStyle.sources };
              for (const [key, value] of Object.entries(previousStyle.sources)) {
                if (key.startsWith('my-polygon')) {
                  sources[key] = value;
                }
              }
    
              return {
                ...nextStyle,
                sources,
                layers,
              };
            }
          });
    
          map.once('styledata', addCustomLayer);
        });
    
        map.on('load', addCustomLayer);
      </script>
    </body>
    </html>

    Now this should be working as intended. :) just add your key