Zum Inhalt springen

Einbau in ein CMS oder Framework

Für TYPO3 und Astro gibt es fertige Pakete. Nehmen Sie die — sie nehmen Ihnen genau den Handgriff ab, an dem ein selbstgebauter Einbau erfahrungsgemäß scheitert.

Die Extension pixelpoint/typo3-pixelmap-widget bringt die Karte als Inhaltselement mit.

Terminal-Fenster
composer require pixelpoint/typo3-pixelmap-widget
  • TYPO3 13.4 LTS und 14.3 LTS, PHP 8.2 bis 8.5
  • Kategorien, Orte, Touren und Inhaltssammlungen werden im Backend aus einer Liste gewählt — keine UUIDs abtippen. ⚠ Für Tour-Kategorien aus dieser Auswahl braucht die Karte das Widget ab 0.14.0: davor blieb eine so gewählte Kategorie wirkungslos, und die Karte zeigte keine Touren — ohne Fehlermeldung.
  • Fünf Inhaltstypen (Ausflugsziele, Touren, Unterkünfte, Veranstaltungen, Erlebnisse) samt Zeitfenster für Veranstaltungen
  • Die Konfiguration kann wahlweise headless als JSON ausgeliefert werden, wenn das Frontend entkoppelt ist

Das Paket liegt in einer GitLab-Composer-Registry, nicht auf Packagist — die Einrichtung steht im README der Extension.

Terminal-Fenster
pnpm add @pixelpoint/pixelmap-astro @innoex/pixelmap-widget maplibre-gl
---
import PixelmapWidget from '@pixelpoint/pixelmap-astro/PixelmapWidget.astro'
---
<PixelmapWidget
configUrl="https://maps.pixelmap.at/demo/config.json"
categories={['uuid1', 'uuid2']}
ctaHref="https://maps.pixelmap.at/demo/"
height="480px"
/>

Dazu eine Zeile in der astro.config.mjs, wenn Sie MapLibre 6 fahren:

import pixelmap from '@pixelpoint/pixelmap-astro/integration'
export default defineConfig({ integrations: [pixelmap()] })

Die Integration erkennt an Ihrer installierten MapLibre-Fassung, ob ein externer Worker gebraucht wird, und verdrahtet ihn. Unter MapLibre 5 tut sie nichts.

Ohne eines der beiden Pakete verdrahten Sie den MapLibre-Worker selbst. Das ist seit Widget 0.12.0 Pflicht und betrifft nur den Bundler-Weg — der Einbau per <script type="module"> braucht es nie.

  1. Ein Plugin, das den Worker findet. Es prüft, ob Ihre MapLibre-Fassung einen externen Worker mitbringt:

    import { createRequire } from 'node:module'
    const require = createRequire(import.meta.url)
    export function maplibreWorkerUrlModule() {
    let workerSpecifier = null
    try {
    require.resolve('maplibre-gl/dist/maplibre-gl-worker.mjs')
    workerSpecifier = 'maplibre-gl/dist/maplibre-gl-worker.mjs?worker&url'
    } catch {
    // MapLibre 5 bündelt seinen Worker inline — dann bleibt WORKER_URL leer.
    }
    const id = 'virtual:maplibre-worker-url'
    const aufgelöst = '\0' + id
    return {
    name: 'maplibre-worker-url',
    resolveId: (quelle) => (quelle === id ? aufgelöst : null),
    load: (i) =>
    i === aufgelöst
    ? workerSpecifier
    ? `export { default } from ${JSON.stringify(workerSpecifier)}`
    : 'export default null'
    : null,
    }
    }

    Eintragen unter plugins Ihrer vite.config.js. Astro-Projekte haben keine vite.config.js — dort gehört es in die astro.config.mjs unter vite: { plugins: [ … ] }.

  2. Die Verdrahtung, im faulen Pfad:

    let pending
    const load = () =>
    (pending ??= (async () => {
    const [{ config }, { default: workerUrl }] = await Promise.all([
    import('maplibre-gl'),
    import('virtual:maplibre-worker-url'),
    ])
    if (workerUrl) config.WORKER_URL = workerUrl
    return import('@innoex/pixelmap-widget')
    })())

    load() rufen Sie, wenn die Karte gebraucht wird. Mehrfach rufen ist unschädlich.

Das Widget baut seine Karte erst auf, wenn es sichtbar wird. Das spart die Karten-Kosten, nicht das Bundle:

Zwei tragfähige Wege, wenn das Gewicht zählt:

  • Fassade: ein statisches Vorschaubild mit Knopf; das <script>-Tag wird erst bei Interaktion eingefügt.
  • Bundler mit dynamischem import() (etwa das Astro-Paket): ein verstecktes Element löst dort null Anfragen aus.

Das Widget wird auf einer fremden Herkunft eingebunden, jede Anfrage ist also herkunftsübergreifend und braucht CORS-Kopfzeilen. Die werden auf maps.pixelmap.at automatisch gesetzt — für jede Karte, ab ihrem ersten Deploy. Es gibt keinen Handgriff je Kunde und keinen je Karte.

Woran Sie eine fehlende Kopfzeile trotzdem erkennen würden (etwa bei einem eigenen, selbst betriebenen Host):

Symptom Ursache
„Karte konnte nicht geladen werden.” statt einer Karte CORS fehlt auf der config.json
Karte da, aber Marker sind einfarbige Punkte statt Symbolen CORS fehlt auf den Symbol-Dateien (/sprites/**) — die Karte funktioniert, sie sieht nur ärmer aus. Ab 0.24.0 fallen dann auch die Symbole in den Sprechblasen auf die mitgelieferte Liste zurück, mit einer Warnung in der Konsole

Ab Widget 0.19.0 meldet das Element drei Ereignisse, auf die Ihre Seite hören kann — etwa um ein Lade-Skelett auszublenden oder eine leere Karte durch einen eigenen Hinweis zu ersetzen. Es sind CustomEvents am <pixelmap-widget>, mit bubbles und composed: Ein Zuhörer am umgebenden Container oder am document hört sie ebenso.

Ereignis Wann event.detail
pixelmap-ready Die Karte ist geladen und die Einträge sind eingespielt — bei jedem erfolgreichen Laden, auch mit 0 Einträgen. { features, tours } (Anzahlen)
pixelmap-empty Direkt nach pixelmap-ready, wenn keine Einträge sichtbar sind. { reason }: collection, no-data oder no-match
pixelmap-error Ein harter Fehler, die Karte ist unbrauchbar — oder die Basiskarte kam gar nicht. { stage, message }, stage: config, init, layers oder tiles
  • reason: collection — die Sammlung war leer oder nicht auflösbar; no-data — es kamen gar keine Einträge an; no-match — Einträge waren da, aber Ihre Auswahl (IDs, Kategorien, Zeitraum) ließ keinen übrig.
  • stage: config — config-url fehlt oder die config.json war nicht ladbar; init — der Aufbau von Daten oder Karte scheiterte; layers — die Karte lud, ihre Ebenen ließen sich nicht einrichten; tiles — binnen 8 s nach dem Laden kam keine einzige Kachel der Basiskarte an. Bei tiles malt das Widget weiter, Marker und Sprechblasen bleiben nutzbar; Ihre Seite entscheidet, was sie daraus macht. Einzelne fehlende Kacheln sind kein Ausfall.
  • message ist technisch und für die Konsole gedacht, nie für Besucher.
  • Bei einer leeren Karte zeigt das Widget selbst einen dezenten Hinweis oben in der Mitte, bei einem Fehler seine Fehlermeldung.
  • Die Ereignisse feuern erst, wenn das Element in den Sichtbereich kommt — dann beginnt das Widget zu laden. Ein Zuhörer, den Sie vor dem Einfügen anlegen, verpasst also nichts.
document.addEventListener('pixelmap-error', (e) => {
console.warn('pixelmap', e.detail.stage, e.detail.message);
});

Das Widget rendert in einem eigenen Shadow DOM und bringt seine Stile mit — Sie importieren kein zusätzliches CSS. An Fremd-Herkünften braucht es den SPA-Host Ihrer Karte (maps.pixelmap.at oder Ihre Kundendomäne) sowie die Kachel-Hosts. Die Links in den Sprechblasen (booking-cta) fügen keine weitere Herkunft hinzu: Sie sind gewöhnliche Links, von dort wird nichts geladen.