<div id="map"></div>

<div class="map-overlay top">
  <div class="map-overlay-inner">
    <h2>Select deaprt_at</h2>
    <label id="departure"></label>
    <input id="slider" type="range" min="0" max="7" step="1" value="0">
  </div>
</div>
body {
  margin: 0;
  padding: 0;
}
#map {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 100%;
}
.map-overlay {
  font: 12px/20px "Helvetica Neue", Arial, Helvetica, sans-serif;
  position: absolute;
  width: 25%;
  top: 0;
  left: 0;
  padding: 10px;
}

.map-overlay .map-overlay-inner {
  background-color: #fff;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
  border-radius: 3px;
  padding: 10px;
  margin-bottom: 10px;
}

.map-overlay h2 {
  line-height: 24px;
  display: block;
  margin: 0 0 10px;
}

.map-overlay input {
  background-color: transparent;
  display: inline-block;
  width: 100%;
  position: relative;
  margin: 0;
  cursor: ew-resize;
}
const center = [139.7668267, 35.6807286];

const departures = [
  "2024-12-03T00:00",
  "2024-12-03T03:00",
  "2024-12-03T06:00",
  "2024-12-03T09:00",
  "2024-12-03T12:00",
  "2024-12-03T15:00",
  "2024-12-03T18:00",
  "2024-12-03T21:00"
];

const minutes = [5, 10, 15];

function getLayerId(departure, minute) {
  return departure + "-" + minute;
}

function filterBy(index) {
  departures.forEach((departure) => {
    minutes.forEach((minute) => {
      const visible = getLayerId(departures[index], minute);
      const id = getLayerId(departure, minute);
      map.setFilter(id, visible === id);
    });
  });

  document.getElementById("departure").textContent = departures[index];
}

mapboxgl.accessToken =
  "pk.eyJ1Ijoib3R0eWxhYiIsImEiOiJjbTNsYmhxdWwwaWJtMnFxenIzNmJuaGJmIn0.QEnCKZZKJQBAbK8GFBzAcw";
const map = new mapboxgl.Map({
  container: "map",
  style: "mapbox://styles/mapbox/light-v11",
  center,
  zoom: 10
});

map.on("load", async () => {
  const tasks = departures.map(async (departure) => {
    return fetch(
      `https://api.mapbox.com/isochrone/v1/mapbox/driving/${center}?contours_minutes=${minutes.join(
        ","
      )}&contours_colors=6706ce,04e813,4286f4&polygons=true&depart_at=${departure}&access_token=${
        mapboxgl.accessToken
      }`
    );
  });

  const responses = await Promise.all(tasks);

  await Promise.all(
    responses.map(async (response) => {
      const departure = response.url.match(
        /depart_at=(\d{4}-\d{2}-\d{2}T\d{2}:\d{2})/
      )[1];

      const features = await response.json();
      map.addSource(departure, {
        type: "geojson",
        data: features
      });

      features.features.forEach((feature) => {
        const minute = feature.properties.contour;
        const id = getLayerId(departure, minute);

        map.addLayer({
          id,
          type: "fill",
          source: departure,
          filter: ["==", ["get", "contour"], minute],
          paint: {
            "fill-color": feature.properties.fillColor,
            "fill-opacity": feature.properties["fill-opacity"]
          }
        });
      });

      return new Promise((resolve) => {
        resolve();
      });
    })
  );

  document.getElementById("slider").addEventListener("input", (e) => {
    filterBy(parseInt(e.target.value, departures.length));
  });

  filterBy(0);
});

External CSS

  1. https://api.mapbox.com/mapbox-gl-js/v2.15.0/mapbox-gl.css

External JavaScript

  1. https://api.mapbox.com/mapbox-gl-js/v2.15.0/mapbox-gl.js