Skip to content
Make with
m

maplibre-label-callout

HTML labels on leader lines

Maintained by Leonel Dias

A MapLibre GL JS plugin that places HTML labels on connector lines from their points, with priorities and collision avoidance so the callouts do not overlap.

Live demo

maplibre-label-callout running on MapLibre GL JS in your browser

Loading the map…

Demo code
import LineCallout3D from "@leoneljdias/maplibre-label-callout";
import type { PluginDemo } from "../types";

export default {
  center: [-9.139, 38.711], // Baixa, Lisbon
  zoom: 14.5,
  run({ map }) {
    type Place = { id: number; name: string; description: string; importance: number };
    const place = (
      id: number,
      name: string,
      description: string,
      importance: number,
      coordinates: [number, number],
    ) => ({
      type: "Feature" as const,
      properties: { id, name, description, importance } satisfies Place,
      geometry: { type: "Point" as const, coordinates },
    });

    // HTML labels on leader lines, placed so they do not overlap.
    new LineCallout3D(map, {
      data: {
        type: "FeatureCollection",
        features: [
          place(1, "Praça do Comércio", "Riverside square", 5, [-9.1366, 38.7076]),
          place(2, "Castelo de São Jorge", "Moorish castle", 4, [-9.1335, 38.7139]),
          place(3, "Rossio", "Central square", 3, [-9.1394, 38.7139]),
          place(4, "Bairro Alto", "Nightlife quarter", 2, [-9.1453, 38.7127]),
          place(5, "Cais do Sodré", "Ferries and trains", 1, [-9.1447, 38.7057]),
        ],
      },
      template: (p: Place) =>
        `<div style="font-weight:600">${p.name}</div><div style="color:#64748b;font-size:10.5px">${p.description}</div>`,
      priority: (p: Place) => p.importance,
      idProperty: "id",
    });
  },
} satisfies PluginDemo;