Pages Map als Web Component

Pages Map als Web Component

Pages Map als Web Component

Die Web Component <done-generic-map> stellt die gemeinsame destination.one-Karte für externe Websites bereit. Datenquelle, Kartenverhalten und UI werden über HTML-Attribute oder über die JavaScript-Properties source und options konfiguriert.

Einbindung

Das Web-Component-Bundle wird einmal in die Host-Seite eingebunden:

  1. <script
  2. type="module"
  3. src="https://newpages.destination.one/web-components.js"
  4. data-language="de"
  5. data-experience="example"
  6. data-template="wlan"
  7. ></script>

Die Karte belegt immer 100 % der Breite und Höhe ihres Elternelements. Das Elternelement muss deshalb eine berechenbare Höhe besitzen:

  1. <div class="map-container">
  2. <done-generic-map source-kind="query" type="Tour,POI"></done-generic-map>
  3. </div>

  4. <style>
  5. .map-container {
  6. width: 100%;
  7. height: 600px;
  8. }
  9. </style>

Ohne eine Höhe am Elternelement hat auch height: 100% der Karte keine sichtbare Höhe.

Datenquellen

source-kind bestimmt, woher die Kartendaten stammen.

query
Lädt Marker über eine META-Suchanfrage. Dies ist der Standard.
items
Zeigt eine vorgegebene Liste von META-Items.
detail
Zeigt ein primäres Detail-Item und optional Wegpunkte, verwandte und empfohlene Items. Tour- oder Area-Geometrien werden unmittelbar angezeigt.
location
Zeigt eine feste Position oder lässt den Benutzer eine Position auf der Karte auswählen. Dieser Modus wird über source oder source-json konfiguriert.



Query-Quelle über HTML

Für eine Query-Quelle stehen folgende Attribute zur Verfügung:

AttributBeschreibung
typeKommagetrennte META-Datentypen, zum Beispiel Tour,POI. Standard: All.
categoriesKommagetrennte Kategorie-IDs.
featuresKommagetrennte Feature-IDs beziehungsweise Feature-Presets.
citiesKommagetrennte Orte.
keywordsKommagetrennte Keywords.
global-idsKommagetrennte global_id-Werte als Query-Filter.
sortMETA-Sortierung.
limitMaximale Markeranzahl. Ohne Angabe gilt der META-Standard von 12.
latitude, longitude, radiusOptionaler Umkreisfilter. Die drei Werte müssen gemeinsam gesetzt werden.
custom-queryVollständige benutzerdefinierte Query. Wenn gesetzt, hat sie Vorrang vor den übrigen Query-Filtern.
search-parameters-jsonVollständige META-Suchparameter als JSON-Objekt.

Items-Quelle über HTML

Mit source-kind="items" kann der WC-Adapter Items anhand ihrer IDs laden:

  1. <done-generic-map
  2. source-kind="items"
  3. global-ids="p_100235769,p_100027802,p_100152965"
  4. ></done-generic-map>

Alternativ akzeptiert items-json ein JSON-Array vollständiger META-Items. Für dynamische Daten ist die JavaScript-Property source vorzuziehen.

Detail-Quelle über HTML

Der Detailmodus lädt das primäre Item über global-id. Nicht explizit übergebene Wegpunkte, verwandte und empfohlene Items werden standardmäßig automatisch geladen.

  1. <done-generic-map
  2. source-kind="detail"
  3. type="Tour"
  4. global-id="t_100267026"
  5. detail-auto-load-items="true"
  6. ></done-generic-map>

detail-auto-load-items="false" deaktiviert das automatische Nachladen. Vollständige Items können über item-json, waypoint-items-json, related-items-json und recommendation-items-json oder über die entsprechenden JavaScript-Properties gesetzt werden.

Location-Quelle

Der feste Modus zeigt einen Marker an der angegebenen Position. Optional wird ein kreisförmiger Radius in Kilometern dargestellt:

  1. map.source = {
  2. kind: 'location',
  3. mode: 'fixed',
  4. position: { lat: 53.1435, lng: 7.3412 },
  5. radiusKm: 5,
  6. showRadius: true,
  7. };

Im Pick-Modus wird der Marker durch einen Kartenklick gesetzt. Die Position wird über das Event location-select ausgegeben:

  1. map.source = {
  2. kind: 'location',
  3. mode: 'pick',
  4. radiusKm: 5,
  5. showRadius: true,
  6. };

GenericMapOptions

Alle Optionen sind optional. Die Spalte „HTML-Attribut“ zeigt das zugehörige flache Attribut der Web Component. Bei booleschen Attributen aktiviert sowohl ein leeres Attribut als auch der Wert "true" die Option; zum Deaktivieren wird ausdrücklich "false" gesetzt.

Karte und Provider

OptionsfeldHTML-AttributStandardBeschreibung
map.clustermap-clustertrueFasst nahe Marker zu Cluster-Bubbles zusammen.
map.userLocationmap-user-latitude, map-user-longitudenicht gesetztZeigt einen zusätzlichen Standortmarker, ohne damit automatisch den initialen Ausschnitt festzulegen. Das Objekt verwendet { lat, lon }.
map.overlap.enabledmap-overlaptrueVersetzt Marker, die auf derselben oder fast derselben Position liegen.
map.overlap.zoomThresholdmap-overlap-zoom-threshold14Ab diesem Zoomlevel werden überlappende Marker versetzt.
map.overlap.offsetMetersmap-overlap-offset-meters8Abstand der versetzten Marker in Metern.
map.providerOptions.enableCloseControlmap-enable-close-controlfalseZeigt das Close-Control des MapLibre-Providers.
map.providerOptions.disableStyleSwitchermap-disable-style-switcherfalseBlendet den Kartenstil-Umschalter aus.
map.providerOptions.defaultStylemap-default-styleaktiver META-KartenstilWählt einen Kartenstil anhand seiner ID aus.
map.providerOptions.stylemap-styleURL des aktiven KartenstilsSetzt direkt eine MapLibre-Style-URL und hat Vorrang vor defaultStyle.
map.providerOptions.centermap-center-longitude, map-center-latitudeMETA-Default-View, sonst DeutschlandInitiales Provider-Zentrum als [longitude, latitude], bevor die Viewport-Logik angewendet wird.
map.providerOptions.zoommap-zoomMETA-Default-View, sonst 9Initialer Provider-Zoom, bevor Fit-Bounds angewendet wird.
map.providerOptions.minZoommap-min-zoomMapLibre-StandardKleinster erlaubter Zoom.
map.providerOptions.maxZoommap-max-zoom18Größter erlaubter Zoom.
map.providerOptions.fitBoundsPaddingmap-fit-bounds-padding100Innerer Abstand in Pixeln beim Einpassen von Markern und Geometrien.
map.providerOptions.customStylesmap-custom-styles-jsonKartenstile aus der META-KonfigurationVerfügbare Kartenstile als Array mit mindestens id und uri; optional sind title und active.
map.providerOptions.mapPinsmap-pins-jsoneingebaute Pin-RegistryZuordnung von Pin-Namen zu SVG-Strings. Die Platzhalter BGCOLOR und FGCOLOR werden durch die Kartenfarben ersetzt.

Viewport

OptionsfeldHTML-AttributStandardBeschreibung
viewport.initialviewport-initial{ mode: 'items' }Initiale Ausrichtung: items, user oder configured.
viewport.initial.locationviewport-latitude, viewport-longitude, viewport-zoomnicht gesetztPosition für viewport-initial="configured".
viewport.fitBoundsviewport-fit-boundstruePasst beim ersten Rendern den Kartenausschnitt an Marker beziehungsweise Geometrie an.
viewport.fitOnItemsChangeviewport-fit-on-items-changetruePasst den Ausschnitt erneut an, wenn sich die übergebenen Items ändern. Benutzergetriebene Query-Reloads unterdrücken dabei unnötige Rücksprünge.
viewport.detailFitviewport-detail-fitDetail: geometry, sonst allIm Detailmodus: geometry fokussiert die Tour/Area, all berücksichtigt zusätzlich alle sichtbaren Markergruppen.

Tour- und Area-Geometrien

OptionsfeldHTML-AttributStandardBeschreibung
geometry.detail.tourgeometry-detail-tourtrueZeigt im Detailmodus die Polyline einer Tour.
geometry.detail.areageometry-detail-areatrueLädt und zeigt im Detailmodus das Polygon einer Area.
geometry.onPinClick.tourgeometry-on-pin-click-tourfalseZeigt nach Auswahl eines Tour-Markers dessen Polyline.
geometry.onPinClick.areageometry-on-pin-click-areafalseLädt und zeigt nach Auswahl eines Area-Markers dessen Polygon.
geometry.directionArrowsgeometry-direction-arrowstrueZeigt Richtungspfeile auf sichtbaren Tour-Polylines.

Die Geometrien werden aus den META-Items beziehungsweise über die dafür vorgesehenen META-Geometrieanfragen ermittelt. Externes GeoJSON muss nicht erzeugt oder übergeben werden.

Routing

OptionsfeldHTML-AttributStandardBeschreibung
routing.enabledrouting-enabledfalseBerechnet eine Route zwischen den sichtbaren Items.
routing.providerrouting-providernicht gesetztID des Routing-Providers. Das Feld ist erforderlich, sobald Routing aktiviert ist.
routing.fromUserrouting-from-userfalseVerwendet den aufgelösten Benutzerstandort als Startpunkt.
routing.numberedPinsrouting-numbered-pinsfalseZeigt die Reihenfolge der Routenziele als Nummern in den Pins.

Ergebnisdichtepunkte

OptionsfeldHTML-AttributStandardBeschreibung
densityPoints.enableddensity-points-enabledfalseZeigt Ergebnisdichtepunkte für den sichtbaren Kartenausschnitt.
densityPoints.searchParametersdensity-points-search-parameters-jsonQuery der Markerquelle ohne PaginationÜberschreibt die Suchparameter der Ergebnisdichtepunkte vollständig.

Die Query kann über folgende flache Attribute überschrieben werden: density-points-custom-query, density-points-type, density-points-categories, density-points-features, density-points-cities, density-points-keywords und density-points-sort. Ohne explizite Density-Query verwendet eine Query-Quelle automatisch die Marker-Query; limit und andere Paginationseinstellungen werden dabei entfernt.

Interaktionen

OptionsfeldHTML-AttributStandardBeschreibung
interactions.initialReloadOnMoveinteractions-initial-reload-on-movefalseAktiviert initial das Nachladen von Query-Ergebnissen nach einer Kartenbewegung.
interactions.debounceMsinteractions-debounce-ms200Verzögerung in Millisekunden, bevor eine Kartenbewegung verarbeitet wird.

Benutzeroberfläche

Einige Defaults sind vom Datenmodus abhängig. „Detail“ bezeichnet source.kind: 'detail'.

OptionsfeldHTML-AttributStandardBeschreibung
ui.fullscreenui-fullscreentrueZeigt das Fullscreen-Control.
ui.categoryFilterui-category-filterDetail: true, sonst falseZeigt im Fullscreen die Filter für Wegpunkte, verwandte und empfohlene Items.
ui.markerDetailui-marker-detailDetail: true, sonst falseÖffnet nach einem Markerklick das eingebaute Detailpanel.
ui.teaserPopupui-teaser-popuptrueErlaubt Teaser-Popups nach einem Klick auf Ergebnisdichtepunkte.
ui.teaserSliderui-teaser-sliderDetail: true, sonst falseZeigt im Detailmodus die sichtbare Zusatzgruppe als Teaser-Slider.
ui.elevationProfileui-elevation-profileDetail: true, sonst falseAktiviert das Höhenprofil für eine sichtbare Tour.
ui.elevationPreviewui-elevation-previewtrueZeigt außerhalb des Fullscreens eine kompakte, anklickbare Höhenprofil-Vorschau, wenn eine Tour ausgewählt ist.
ui.fullscreenInsetTopui-fullscreen-inset-topvar(--pageheader-height, 0px)Reserviert oberhalb der Fullscreen-Karte Platz, beispielsweise für einen festen Seitenheader.
ui.showReloadOnMoveToggleui-show-reload-on-move-togglefalseZeigt den Schalter „Ergebnisse beim Bewegen der Karte aktualisieren“.
ui.linkTargetlink-target_selfZielkontext der Detail- und Teaserlinks, zum Beispiel _self oder _blank.
ui.linkDetailBaseUrllink-detail-base-urldestination.one-Standalone-URLBasis-URL für externe Detaillinks. Ohne Angabe wird die Standalone-URL aus Sprache, Experience und Template erzeugt.
ui.linkRouterModelink-router-modehistoryForm der Links bei eigener Basis-URL: history erzeugt /detail/..., hash erzeugt #/detail/.... Ohne eigene Basis-URL bleibt der Standalone-Link immer im History-Format.

Beschriftungen

Die Standardwerte stammen aus den Übersetzungen der konfigurierten Sprache.

OptionsfeldHTML-AttributBeschreibung
ui.labels.updateResultsOnMovelabel-update-results-on-moveBeschriftung des Movement-Reload-Schalters.
ui.labels.iconStylelabel-icon-styleZugänglicher Name des Style-Switchers.
ui.labels.iconMaximizelabel-icon-maximizeZugänglicher Name des Maximieren-Controls.
ui.labels.iconMinimizelabel-icon-minimizeZugänglicher Name des Minimieren-Controls.
ui.labels.iconCloselabel-icon-closeZugänglicher Name des Close-Controls.
ui.labels.fullscreenDialoglabel-fullscreen-dialogZugänglicher Name des Fullscreen-Dialogs.

Vollständiges HTML-Beispiel mit flachen Attributen

Flache Attribute sind für CMS- und statische HTML-Einbindungen vorgesehen:

  1. <div class="tour-map">
  2. <done-generic-map
    source-kind="query"
    type="Tour"
    categories="Wandern,Radtouren"
    sort="title"
    limit="24"
    map-cluster="true"
    viewport-fit-bounds="true"
    geometry-on-pin-click-tour="true"
    geometry-direction-arrows="true"
    density-points-enabled="true"
    interactions-initial-reload-on-move="false"
    ui-fullscreen="true"
    ui-marker-detail="true"
    ui-teaser-popup="true"
    ui-elevation-profile="true"
    ui-elevation-preview="true"
    ui-show-reload-on-move-toggle="true"
    link-target="_self"
    ></done-generic-map>
  3. source-kind="query"
  4. type="Tour"
  5. categories="Wandern,Radtouren"
  6. sort="title"
  7. limit="24"
  8. map-cluster="true"
  9. viewport-fit-bounds="true"
  10. geometry-on-pin-click-tour="true"
  11. geometry-direction-arrows="true"
  12. density-points-enabled="true"
  13. interactions-initial-reload-on-move="false"
  14. ui-fullscreen="true"
  15. ui-marker-detail="true"
  16. ui-teaser-popup="true"
  17. ui-elevation-profile="true"
  18. ui-elevation-preview="true"
  19. ui-show-reload-on-move-toggle="true"
  20. link-target="_self"
  21. ></done-generic-map>
  22. </div>

  23. <style>
  24. .tour-map {
  25. width: 100%;
  26. height: min(700px, 80vh);
  27. }
  28. </style>

Komplexe Konfigurationen können alternativ als JSON über source-json und options-json übergeben werden. Für dynamische Daten sind echte JavaScript-Objekte besser geeignet.

JavaScript-Beispiel mit Objekt-Properties

Die Properties source und options übernehmen echte Objekte. Das Element wird zuerst in das DOM eingefügt, damit der Lazy Loader die Web Component registriert. Anschließend wartet der Code auf die Definition und setzt die Properties:

  1. <div id="map-host">
  2. <done-generic-map id="map"></done-generic-map>
  3. </div>

  4. <style>
  5. #map-host {
  6. width: 100%;
  7. height: 600px;
  8. }
  9. </style>

  10. <script type="module">
  11. await customElements.whenDefined('done-generic-map');

  12. const map = document.querySelector('#map');

  13. map.source = {
  14. kind: 'query',
  15. searchParameters: {
  16. type: 'Tour',
  17. category: 'Wandern',
  18. limit: 24,
  19. sort: 'title',
  20. cause: 'newpages.portal',
  21. },
  22. };

  23. map.options = {
  24. map: {
  25. cluster: true,
  26. overlap: {
  27. enabled: true,
  28. zoomThreshold: 14,
  29. offsetMeters: 8,
  30. },
  31. },
  32. viewport: {
  33. initial: { mode: 'items' },
  34. fitBounds: true,
  35. fitOnItemsChange: true,
  36. },
  37. geometry: {
  38. onPinClick: {
  39. tour: true,
  40. area: true,
  41. },
  42. directionArrows: true,
  43. },
  44. densityPoints: {
  45. enabled: true,
  46. },
  47. ui: {
  48. fullscreen: true,
  49. markerDetail: true,
  50. teaserPopup: true,
  51. elevationProfile: true,
  52. elevationPreview: true,
  53. linkTarget: '_self',
  54. },
  55. };

  56. map.addEventListener('marker-click', (event) => {
  57. const payload = event.detail[0];
  58. console.log('Marker ausgewählt:', payload.item);
  59. });

  60. map.addEventListener('update:fullscreen', (event) => {
  61. console.log('Fullscreen:', event.detail[0]);
  62. });
  63. </script>

Bei einer dynamischen Änderung wird der Property ein neues Objekt zugewiesen. Das direkte Mutieren eines tief verschachtelten Feldes ist von außen nicht zuverlässig beobachtbar:

  1. map.options = {
  2. ...map.options,
  3. ui: {
  4. ...map.options.ui,
  5. markerDetail: false,
  6. },
  7. };

Konfigurationspriorität

Wenn dieselbe Option mehrfach gesetzt ist, gilt folgende Priorität:

  1. JavaScript-Property options
  2. flache HTML-Attribute
  3. options-json
  4. interne Standardwerte

Für die Quelle gilt: source vor source-json vor den flachen Source-Attributen.

Events

Vue Custom Elements geben die Argumente eines Events als Array in CustomEvent.detail aus. Bei den folgenden Events liegt die Nutzlast daher jeweils in event.detail[0].

EventNutzlastBedeutung
ready{ mapId }Die Kartenlaufzeit ist bereit.
loadedMetaItem[]Die Items der Quelle wurden geladen beziehungsweise übernommen.
errorstringKonfigurations-, Request- oder Kartenfehler.
marker-click{ id, item, coordinates }Ein Marker wurde ausgewählt.
marker-deselect{ item, coordinates }Der bereits ausgewählte Marker wurde abgewählt.
feature-click{ id, item, coordinates }Allgemeines Feature-Click-Event für Marker.
density-point-click{ item, coordinates }Ein Ergebnisdichtepunkt wurde aufgelöst und ausgewählt.
location-select{ lat, lng }Der Benutzer hat im Location-Pick-Modus eine Position gewählt.
viewport-change{ bounds, zoom }Sichtbarer Kartenausschnitt oder Zoom haben sich geändert.
update-results{ boundsQuery, bounds }Bei aktiviertem Movement-Reload sollen Ergebnisse für den neuen Ausschnitt geladen werden.
reload-on-move-changebooleanDer Benutzer hat den Movement-Reload-Schalter geändert.
update:fullscreenbooleanDer Fullscreen-Zustand hat sich geändert.
update:activeCategoriesstring[]Die aktiven Detail-Kategorien haben sich geändert.
update:selectedItemMetaItem | nullDie kontrollierte Markerauswahl hat sich geändert.
close-requestkeineDas Close-Control fordert den Host zum Schließen der Karte auf.

Die Zustände fullscreen, active-categories und selected-item sind kontrollierbar. Wenn der Host einen solchen Wert dauerhaft als Attribut oder Property setzt, muss er auf das zugehörige update:*-Event reagieren und den Wert aktualisieren, damit Benutzeränderungen bestehen bleiben.