Archived

Documentation for Layer Cake v10, before Svelte 5 runes. Current docs at layercake.graphics

Menu

MapLabels.svg.svelte component

Adds SVG text labels based on features in the data or a custom GeoJSON Feature Collection.

Param Default Required Description
projection Function None
yes
A D3 projection function. Pass this in as an uncalled function, e.g. projection={geoAlbersUsa}.
getLabel (d: any) => string None
yes
Returns the label text for a feature.
getCoordinates (d: any) => [number, number] None
yes
Returns the [x, y] coordinate pair to project for a feature, e.g. d => d.geometry.coordinates.
fixedAspectRatio (number | undefined) None
no
By default, the map fills to fit the k.width and k.height. If instead you want a fixed-aspect ratio, like for a server-side rendered map, set that here.
features (Array<Object> | undefined) None
no
A list of labels as GeoJSON features. If unset, the plotted features will default to those in k.data.features, assuming this field is a list of GeoJSON features.
<!--
  @component
  Adds SVG text labels based on features in the data or a custom GeoJSON Feature Collection.
 -->
<script>
  import { getLayerCakeContext } from 'layercake';

  /** @type {import('layercake').LayerCakeContext<any, { features: Array<any> }>} */
  const k = getLayerCakeContext();

  /**
   * @typedef {Object} Props
   * @property {Function} projection - A D3 projection function. Pass this in as an uncalled function, e.g. `projection={geoAlbersUsa}`.
   * @property {(d: any) => string} getLabel - Returns the label text for a feature.
   * @property {(d: any) => [number, number]} getCoordinates - Returns the `[x, y]` coordinate pair to project for a feature, e.g. `d => d.geometry.coordinates`.
   * @property {number|undefined} [fixedAspectRatio] - By default, the map fills to fit the k.width and k.height. If instead you want a fixed-aspect ratio, like for a server-side rendered map, set that here.
   * @property {Array<Object>|undefined} [features] - A list of labels as GeoJSON features. If unset, the plotted features will default to those in `k.data.features`, assuming this field is a list of GeoJSON features.
   */

  /** @type {Props} */
  let { projection, getLabel, getCoordinates, fixedAspectRatio, features } = $props();

  let fitSizeRange = $derived(
    fixedAspectRatio ? [100, 100 / fixedAspectRatio] : [k.width, k.height]
  );

  let projectionFn = $derived(projection().fitSize(fitSizeRange, k.data));
</script>

<g class="map-labels">
  {#each features || k.data.features as d}
    {@const coords = projectionFn(getCoordinates(d))}
    <text class="map-label" x={coords[0]} y={coords[1]}>{getLabel(d)}</text>
  {/each}
</g>

<style>
  .map-labels {
    pointer-events: none;
  }
  .map-label {
    fill: #333;
    /* Inside a ScaledSvg layout, which scales everything up about 10x, use about 1px */
    font-size: 8px;
    text-anchor: middle;
  }
</style>