Query Features

Query source and rendered features to place markers and display a list.

<script lang="ts">
  import {
    MapLibre,
    GeoJSONSource,
    CircleLayer,
    Marker,
    GlobeControl,
    QuerySourceFeatures,
    QueryRenderedFeatures
  } from 'svelte-maplibre-gl';
  import maplibregl from 'maplibre-gl';
  import * as Tabs from '$lib/components/ui/tabs/index.js';

  let map: maplibregl.Map | undefined = $state();
  let features: maplibregl.MapGeoJSONFeature[] = $state.raw([]);
  let mode: 'source' | 'rendered' = $state('source');
</script>

<div class="flex h-[55vh] min-h-[300px] gap-x-3">
  <MapLibre
    bind:map
    class="h-[55vh] min-h-[300px] grow"
    style="https://basemaps.cartocdn.com/gl/voyager-gl-style/style.json"
    zoom={3}
    center={{ lng: 120, lat: 20 }}
  >
    <GlobeControl />
    <GeoJSONSource
      id="earthquakes"
      data={'https://maplibre.org/maplibre-gl-js/docs/assets/significant-earthquakes-2015.geojson'}
      promoteId="ids"
    >
      {#if mode == 'source'}
        <!-- map.querySourceFeatures() -->
        <QuerySourceFeatures bind:features>
          {#snippet children(feature: maplibregl.MapGeoJSONFeature)}
            {#if feature.geometry.type === 'Point'}
              <Marker lnglat={feature.geometry.coordinates as [number, number]} />
            {/if}
          {/snippet}
        </QuerySourceFeatures>
      {/if}
      <CircleLayer paint={{ 'circle-color': 'red', 'circle-radius': 4 }}>
        {#if mode == 'rendered'}
          <!-- map.queryRenderedFeatures() -->
          <QueryRenderedFeatures bind:features>
            {#snippet children(feature: maplibregl.MapGeoJSONFeature)}
              {#if feature.geometry.type === 'Point'}
                <Marker lnglat={feature.geometry.coordinates as [number, number]} />
              {/if}
            {/snippet}
          </QueryRenderedFeatures>
        {/if}
      </CircleLayer>
    </GeoJSONSource>
  </MapLibre>

  <!-- List of earthquakes -->
  <div class="relative basis-[10em]">
    <Tabs.Root bind:value={mode} class="flex h-full flex-col">
      <Tabs.List class="grid w-full grid-cols-2">
        <Tabs.Trigger value="source">Source</Tabs.Trigger>
        <Tabs.Trigger value="rendered">Rendered</Tabs.Trigger>
      </Tabs.List>
      <Tabs.Content value="source" class="min-h-0 shrink overflow-scroll">
        <ul class="m-0 ml-2 overflow-scroll px-3 text-xs">
          {#each features as feature}
            <li>{feature.properties.title}</li>
          {/each}
        </ul>
      </Tabs.Content>
      <Tabs.Content value="rendered" class="min-h-0 shrink overflow-scroll">
        <ul class="m-0 ml-4 overflow-scroll px-3 text-xs">
          {#each features as feature}
            <li>{feature.properties.title}</li>
          {/each}
        </ul>
      </Tabs.Content>
    </Tabs.Root>
  </div>
</div>