Feature: Hover-Vorschau auf Kartenmarkern
Marker zeigen jetzt beim Mouseover zusaetzlich zum bestehenden Klick-Popup eine kompakte Vorschau (Leaflet-Tooltip) mit Name, Kategorie, Kurzbeschreibung sowie Kurzfakten (Altersempfehlung, Kostenart, Bewertung, falls vorhanden) - ohne dass geklickt werden muss. Inhalt wird wie ueberall sonst als DOM-Node ueber el()/textContent erzeugt, kein innerHTML.
This commit is contained in:
@@ -220,3 +220,45 @@
|
|||||||
font-size: 0.85rem;
|
font-size: 0.85rem;
|
||||||
color: var(--color-text-muted);
|
color: var(--color-text-muted);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Hover-Vorschau (Leaflet-Tooltip) auf Kartenmarkern */
|
||||||
|
|
||||||
|
.leaflet-tooltip.eventmap-tooltip-wrapper {
|
||||||
|
background: var(--color-surface);
|
||||||
|
color: var(--color-text);
|
||||||
|
border: none;
|
||||||
|
border-radius: var(--radius-sm);
|
||||||
|
box-shadow: var(--shadow-card);
|
||||||
|
padding: var(--space-sm) var(--space-md);
|
||||||
|
}
|
||||||
|
|
||||||
|
.leaflet-tooltip.eventmap-tooltip-wrapper::before {
|
||||||
|
border-top-color: var(--color-surface);
|
||||||
|
}
|
||||||
|
|
||||||
|
.eventmap-tooltip {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 4px;
|
||||||
|
max-width: 220px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.eventmap-tooltip__title {
|
||||||
|
font-size: 0.9rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.eventmap-tooltip__category {
|
||||||
|
font-size: 0.78rem;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.eventmap-tooltip__desc {
|
||||||
|
font-size: 0.82rem;
|
||||||
|
color: var(--color-text-muted);
|
||||||
|
}
|
||||||
|
|
||||||
|
.eventmap-tooltip__facts {
|
||||||
|
font-size: 0.78rem;
|
||||||
|
color: var(--color-text-muted);
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|||||||
@@ -41,6 +41,46 @@
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const COST_LABELS = { free: 'Kostenlos', paid: 'Kostenpflichtig', mixed: 'Teils kostenpflichtig', unknown: null };
|
||||||
|
|
||||||
|
function formatTooltipAge(ageRecommendation) {
|
||||||
|
const { min, max } = ageRecommendation || {};
|
||||||
|
if (min == null && max == null) return null;
|
||||||
|
if (min != null && max != null) return `${min}–${max} Jahre`;
|
||||||
|
if (min != null) return `Ab ${min} Jahren`;
|
||||||
|
return `Bis ${max} Jahre`;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Kompakte Hover-Vorschau (Leaflet-Tooltip), zusätzlich zum Klick-Popup. */
|
||||||
|
function buildTooltipContent(place) {
|
||||||
|
const category = getPlaceCategory(place);
|
||||||
|
|
||||||
|
const facts = [];
|
||||||
|
const age = formatTooltipAge(place.ageRecommendation);
|
||||||
|
if (age) facts.push(age);
|
||||||
|
const costLabel = COST_LABELS[(place.cost || {}).type];
|
||||||
|
if (costLabel) facts.push(costLabel);
|
||||||
|
if (typeof place.rating === 'number') facts.push(`★ ${place.rating.toFixed(1)}`);
|
||||||
|
|
||||||
|
const children = [
|
||||||
|
el('strong', { className: 'eventmap-tooltip__title', text: place.name }),
|
||||||
|
el('div', {
|
||||||
|
className: 'eventmap-tooltip__category',
|
||||||
|
style: { color: category.color },
|
||||||
|
text: `${category.icon} ${category.label}`,
|
||||||
|
}),
|
||||||
|
];
|
||||||
|
|
||||||
|
if (place.shortDescription) {
|
||||||
|
children.push(el('p', { className: 'eventmap-tooltip__desc', text: place.shortDescription }));
|
||||||
|
}
|
||||||
|
if (facts.length > 0) {
|
||||||
|
children.push(el('p', { className: 'eventmap-tooltip__facts', text: facts.join(' · ') }));
|
||||||
|
}
|
||||||
|
|
||||||
|
return el('div', { className: 'eventmap-tooltip' }, children);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Erzeugt einen Leaflet-Marker für ein Place-Objekt.
|
* Erzeugt einen Leaflet-Marker für ein Place-Objekt.
|
||||||
* @param {object} place
|
* @param {object} place
|
||||||
@@ -51,6 +91,17 @@
|
|||||||
const marker = L.marker([lat, lng], { icon: getIconForCategory(place.category) });
|
const marker = L.marker([lat, lng], { icon: getIconForCategory(place.category) });
|
||||||
|
|
||||||
marker.bindPopup(buildPopupContent(place));
|
marker.bindPopup(buildPopupContent(place));
|
||||||
|
// Hover-Vorschau zusätzlich zum Klick-Popup: sticky folgt dem Mauszeiger,
|
||||||
|
// damit die Vorschau nicht die Position wechselt, während man über den
|
||||||
|
// Marker fährt. Schließt sich automatisch bei mouseout bzw. wenn der
|
||||||
|
// Klick-Popup geöffnet wird.
|
||||||
|
marker.bindTooltip(buildTooltipContent(place), {
|
||||||
|
direction: 'top',
|
||||||
|
offset: [0, -18],
|
||||||
|
opacity: 0.97,
|
||||||
|
sticky: false,
|
||||||
|
className: 'eventmap-tooltip-wrapper',
|
||||||
|
});
|
||||||
marker.on('click', () => {
|
marker.on('click', () => {
|
||||||
if (onSelect) {
|
if (onSelect) {
|
||||||
onSelect(place.id);
|
onSelect(place.id);
|
||||||
|
|||||||
Reference in New Issue
Block a user