Filtrar com segmentações

As segmentações de dados são os controles de filtro que o autor colocou no mapa. Os chips à esquerda são construídos a partir do que o mapa informa (as segmentações, os valores que cada uma oferece e o estado atual) e ficam em sincronia com os cartões de segmentação do próprio mapa (no canto superior direito do mapa): clique em um chip e o cartão acompanha; use um cartão e os chips acompanham. Definir uma segmentação por script é exatamente o mesmo que o leitor usá-la, então todas as camadas e gráficos vinculados a ela acompanham.

Abrir este exemplo separadamente

O que observar

  • getSlicers() as lista; getSlicerValues() retorna os valores que uma segmentação de lista oferece.
  • O estado de uma segmentação de lista é { values: [...] }; null a limpa. Os outros tipos recebem value, range, date, dateRange, relativeDate, timeRange ou toggled.
  • Um único manipulador de slicerChanged cobre as suas alterações (reason: "command") e as do leitor ("user").
  • Ocultar uma segmentação a desativa: sua seleção deixa de filtrar, como acontece em um indicador. Para filtrar sem nenhum cartão no mapa, use filtros declarados (o próximo exemplo).

O código

A página completa. Troque pelo seu próprio ID de publicação e peça ao autor do mapa que adicione seu site às origens permitidas dele.

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Filter with slicers - Icon Map Embed API</title>
  <link rel="stylesheet" href="https://www.icon-map.com/embed-examples/examples.css"> <!-- demo styling only -->
</head>
<body>
  <div class="ex-main">
    <div class="ex-side">
      <div id="panels">loading...</div>
      <h2>Result</h2>
      <pre class="ex-readout" id="result"></pre>
      <div class="ex-chips" style="margin-top:10px">
        <button id="clear">Clear all</button>
        <button id="fit">Frame the result</button>
      </div>
    </div>
    <div id="map"></div>
  </div>

  <script src="https://www.icon-map.com/js/iconmap-embed/2/iconmap-embed.umd.min.js"></script>
  <script>
    const el = document.getElementById("map");
    const map = IconMapEmbed.embed(el, {
      publishId: "pub_...",
      // The map is a globe: let this page's own background show in the space around it.
      background: "transparent",
      chrome: { legend: false, layerControl: false, bookmarksBar: false, tourTransport: false },
      // The map's slicer cards stay on (top right): use one and the chips follow, click a chip and
      // the card follows. Only the chart is hidden. Hiding a slicer would switch it OFF - to filter
      // with no card on the map, use filters instead (see "Filter from your page").
      visibility: { visuals: { "chart-continent": false } },
      events: ["slicerChanged"],
    });
    map.ready.catch((error) => console.error(error.code, error.message));

    const chosen = {};   // slicerId -> Set of values

    // The slicers, their fields and the values each offers all come from the map.
    map.getSlicers().then(async (slicers) => {
      const host = document.getElementById("panels");
      host.textContent = "";
      for (const slicer of slicers) {
        chosen[slicer.id] = new Set(slicer.state?.values ?? []);
        const { values } = await map.getSlicerValues({ slicerId: slicer.id });
        const title = Object.assign(document.createElement("h2"), { textContent: slicer.name });
        const chips = Object.assign(document.createElement("div"), { className: "ex-chips" });
        for (const value of values) {
          const chip = Object.assign(document.createElement("button"), { textContent: String(value).replace(/^\d\. /, "") });
          chip.dataset.slicer = slicer.id;
          chip.dataset.value = value;
          chip.onclick = () => toggle(slicer.id, String(value));
          chips.append(chip);
        }
        host.append(title, chips);
      }
      paint();
    });

    // Setting a slicer is exactly the reader using it: every layer and chart bound to it follows.
    // A list slicer's state is { values: [...] }; null clears it.
    function toggle(slicerId, value) {
      const set = chosen[slicerId];
      set.has(value) ? set.delete(value) : set.add(value);
      return map.setSlicerState({ slicerId, state: set.size ? { values: [...set] } : null });
    }

    document.getElementById("clear").onclick = () => map.clearAllSlicers();
    document.getElementById("fit").onclick = () => map.fitLayer({ layerId: "cities", padding: 30, maxZoom: 6 });

    // One handler covers your own changes (reason "command") and the reader's ("user").
    map.on("slicerChanged", ({ slicerId, state }) => {
      chosen[slicerId] = new Set(state?.values ?? []);
      setTimeout(paint, 300);   // give the map a moment to re-filter before counting
    });

    async function paint() {
      for (const chip of document.querySelectorAll("[data-slicer]")) {
        chip.classList.toggle("on", chosen[chip.dataset.slicer]?.has(chip.dataset.value) === true);
      }
      const stats = await map.getLayerStats({ layerId: "cities" });
      document.getElementById("result").textContent = `${stats.visibleFeatureCount.toLocaleString()} cities match`;
    }
  </script>
</body>
</html>

Saiba mais