style 変更方法 (MapLibre)

こんにちは。
MapLibre の style 変更方法を見つけ試しました。
特徴は、変更後も、```map.addLayer()```していた内容が表示されます。
* [Display a style switcher control](https://gist.github.com/eis-ioki/81d7a02cc00d9ecb2c949d101841ef81) (gist.github.com/eis-ioki)[^1][^2]

[^1]: 参考：[map.SetStyle\(...\) conflicts with custom render layers #2587](https://github.com/maplibre/maplibre-gl-js/issues/2587) (maplibre-gl-js)
[^2]: 参考：[Swap baselayer with a persistent data layer on top](https://gist.github.com/tristen/0c0ed34e210a04e89984) (https://gist.github.com/tristen; mapbox-gl-js)



<img width="300" alt="スクリーンショット 2024-09-03 20.04.37.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/54617/fedb5ced-a5f4-64a2-5bed-ff3cbd3a3295.jpeg">

#### ソース
```maplibre.html
<!DOCTYPE html>
<!--https://gist.github.com/eis-ioki/81d7a02cc00d9ecb2c949d101841ef81-->
<html>
<head>
  <meta charset="utf-8" />
  <title>Display a style switcher control</title>
  <meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" />
  <script src='https://unpkg.com/maplibre-gl@latest/dist/maplibre-gl.js'></script>
  <link href='https://unpkg.com/maplibre-gl@latest/dist/maplibre-gl.css' rel='stylesheet' />
    <style>
        body {
          margin: 0;
          padding: 0;
        }
        #map {
          position: absolute;
          top: 0;
          bottom: 0;
          width: 100%;
        }
        #selectStyle { position: absolute; top: 10px; left:10px; background: #fff; opacity: 0.7;}
    </style>
</head>
<body>
    <div id="map"></div>
    <select id='selectStyle'></select>
    <script>
    const KEY_MAPTILER = '';
    const styles = ["positron", "darkmatter", "basic", "bright", "openstreetmap"];
    const map = new maplibregl.Map({
      container: 'map', // container's id or the HTML element to render the map
      style: getStyle(styles[0]),
      center: [100.507, 13.7231], // starting position [lng, lat]
      zoom: 9, // starting zoom
    });

  // selecting styles
    const selectStyle = document.getElementById("selectStyle"); 
    selectStyle.setAttribute('onchange', 'swapStyle()');
    const source_name = "my-polygon";

    for (const style of styles) {
        const el = document.createElement("option");
        el.textContent = style;
        el.value = getStyle(style);
        selectStyle.appendChild(el);
    };

    function getStyle(style) {
      return `https://api.maptiler.com/maps/${style}/style.json?key=${KEY_MAPTILER}`;
    }

    function swapStyle() {
        map.setStyle(selectStyle.value,
          {
            transformStyle: (previousStyle, nextStyle) => {
              const custom_layers = previousStyle.layers.filter((layer) => {
                if (layer.source) {
                  return layer.source.startsWith(source_name);
                }
              });

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

              return {
                ...nextStyle,
                sources: sources,
                layers: layers,
              };
            }
          });
    }


    map.on('load', () => {
      map.addSource(source_name, {
        'type': 'geojson',
        'data': {
          'type': 'Feature',
          'properties': {},
          'geometry': {
            'coordinates': [[[100.53964892087583, 13.660619302818347], [100.55270773339066, 13.656594955333276], [100.56447974562076, 13.656218852501112], [100.57262868151253, 13.662002117894474], [100.58543315884884, 13.675699877504414], [100.58983114957277, 13.686759143623831], [100.58504647855904, 13.695809081244136], [100.57547435674053, 13.70146360409629], [100.5572383326392, 13.706485298786717], [100.55206319844564, 13.702593104288496], [100.55257848387004, 13.685378344393015], [100.54688820693679, 13.67130134979763], [100.5387425326955, 13.668787883326601], [100.53964892087583, 13.660619302818347]]],
            'type': 'Polygon'
          }
        }
      });
      map.addLayer({
        'id': source_name,
        'type': 'fill',
        'source': source_name,
        'layout': {},
        'paint': {
          'fill-color': '#FF0000',
          'fill-opacity': 0.5
        }
      });
    });
  </script>
</body>
</html>
```