Mapa asynchroniczność, kontrastowanie linków

This commit is contained in:
dm
2025-11-26 16:06:29 +01:00
parent a0f4e8fbab
commit 9b5eb5a3ef
3 changed files with 88 additions and 75 deletions

View File

@@ -1,9 +1,6 @@
--- ---
import "../../styles/map-google.css"; import "../../styles/map-google.css";
/**
* PARAMETRY MAPY
*/
const { const {
apiKey, apiKey,
lat, lat,
@@ -16,11 +13,9 @@ const {
mapStyleId = "8e0a97af9476f2d3" mapStyleId = "8e0a97af9476f2d3"
} = Astro.props; } = Astro.props;
/** ID kontenera w DOM */
const domId = `fuz-map-${Math.random().toString(36).slice(2)}`; const domId = `fuz-map-${Math.random().toString(36).slice(2)}`;
--- ---
<!-- Kontener na mapę -->
<div <div
id={domId} id={domId}
class={ class={
@@ -36,35 +31,34 @@ const domId = `fuz-map-${Math.random().toString(36).slice(2)}`;
data-title={title} data-title={title}
data-desc={description} data-desc={description}
data-showmarker={showMarker} data-showmarker={showMarker}
/></div> ></div>
<script is:inline define:vars={{ apiKey, domId, mapStyleId }}> <script is:inline define:vars={{ apiKey, domId, mapStyleId }}>
/**
* ⭐ FINALNY GOOGLE MAPS API LOADER 2025 ⭐
* ------------------------------------------
* - Bez callbacków
* - Bez deprecated Marker
* - Zgodny z importLibrary()
* - Zero warningów o async / mapId
* - Stabilny w Astro (Vite SSR + SPA)
*/
(function () { (function () {
/** Ładowanie Google Maps API — stabilna wersja */
async function loadGoogleMaps(apiKey) { async function loadGoogleMaps(apiKey) {
// Jeśli już załadowane if (window.google?.maps?.importLibrary) return;
if (window.google?.maps) return window.google.maps;
// Jeśli trwa ładowanie — użyj tego samego Promise
if (!window._GOOGLE_MAPS_LOADING) { if (!window._GOOGLE_MAPS_LOADING) {
window._GOOGLE_MAPS_LOADING = new Promise((resolve, reject) => { window._GOOGLE_MAPS_LOADING = new Promise((resolve, reject) => {
const script = document.createElement("script"); const script = document.createElement("script");
script.src = `https://maps.googleapis.com/maps/api/js?key=${apiKey}&v=weekly`; script.src = `https://maps.googleapis.com/maps/api/js?key=${apiKey}&loading=async&v=weekly`;
script.async = true; script.async = true;
script.defer = true; script.defer = true;
script.onerror = () => reject("Google Maps API failed to load"); script.onerror = () => reject("Google Maps API failed to load");
script.onload = () => resolve(window.google.maps);
// Czekamy na google.maps.importLibrary
script.onload = () => {
const checkReady = () => {
if (window.google?.maps?.importLibrary) {
resolve();
} else {
setTimeout(checkReady, 50);
}
};
checkReady();
};
document.head.appendChild(script); document.head.appendChild(script);
}); });
} }
@@ -72,68 +66,64 @@ const domId = `fuz-map-${Math.random().toString(36).slice(2)}`;
return window._GOOGLE_MAPS_LOADING; return window._GOOGLE_MAPS_LOADING;
} }
/** ★ Inicjalizacja pojedynczej mapy */
async function initMap() { async function initMap() {
const el = document.getElementById(domId); const el = document.getElementById(domId);
if (!el) return; if (!el) return;
/** 1. Ładujemy API */ try {
const maps = await loadGoogleMaps(apiKey); await loadGoogleMaps(apiKey);
/** 2. importLibrary — NOWE Google API 2025 */ const { Map } = await google.maps.importLibrary("maps");
const { Map } = await maps.importLibrary("maps"); const { AdvancedMarkerElement } = await google.maps.importLibrary("marker");
const { AdvancedMarkerElement } = await maps.importLibrary("marker");
const { InfoWindow } = await maps.importLibrary("maps");
/** 3. Dane konfiguracyjne mapy z data-* */ const lat = Number(el.dataset.lat);
const lat = Number(el.dataset.lat); const lon = Number(el.dataset.lon);
const lon = Number(el.dataset.lon); const zoom = Number(el.dataset.zoom);
const zoom = Number(el.dataset.zoom); const title = el.dataset.title || "";
const title = el.dataset.title || ""; const desc = el.dataset.desc || "";
const desc = el.dataset.desc || ""; const showMarker = el.dataset.showmarker === "true";
const showMarker = el.dataset.showmarker === "true";
/** 4. Tworzymy mapę z nowym mapId */ const map = new Map(el, {
const map = new Map(el, { center: { lat, lng: lon },
center: { lat, lng: lon }, zoom,
zoom, mapId: mapStyleId,
mapId: mapStyleId, // ★★ wymagane 2024+ ★★ mapTypeControl: false,
mapTypeControl: false, fullscreenControl: false,
fullscreenControl: false, streetViewControl: false,
streetViewControl: false, scrollwheel: false,
scrollwheel: false, zoomControl: true,
zoomControl: true,
});
/** Zapamiętanie referencji */
window.fuzMaps = window.fuzMaps || {};
window.fuzMaps[domId] = map;
/** 5. Marker 2025 (AdvancedMarkerElement) */
if (showMarker) {
const marker = new AdvancedMarkerElement({
map,
position: { lat, lng: lon }
}); });
if (title || desc) { window.fuzMaps = window.fuzMaps || {};
const info = new InfoWindow({ window.fuzMaps[domId] = map;
content: `
<div class="f-info-window"> if (showMarker) {
<div class="f-info-header"> const marker = new AdvancedMarkerElement({
<div class="f-info-city">${title}</div> map,
<div class="f-info-street">${desc}</div> position: { lat, lng: lon }
</div>
</div>
`
}); });
info.open({ map, anchor: marker }); if (title || desc) {
const { InfoWindow } = await google.maps.importLibrary("maps");
const info = new InfoWindow({
content: `
<div class="f-info-window">
<div class="f-info-header">
<div class="f-info-city">${title}</div>
<div class="f-info-street">${desc}</div>
</div>
</div>
`
});
info.open({ map, anchor: marker });
}
} }
} catch (error) {
console.error("Error initializing map:", error);
} }
} }
/** Start po załadowaniu DOM */
document.addEventListener("DOMContentLoaded", initMap); document.addEventListener("DOMContentLoaded", initMap);
})(); })();

View File

@@ -1,6 +1,6 @@
@layer components { @layer components {
.f-footer { .f-footer {
@apply mt-2 border-t border-[--f-input-border] bg-[--f-background-o] text-[--f-text] pt-2; @apply mt-2 border-t border-[--f-input-border] bg-[--f-footer-background] text-[--f-text] pt-2;
} }
.f-footer-inner { .f-footer-inner {
@@ -20,7 +20,7 @@
} }
a { a {
@apply text-[--f-link-text]; @apply text-[--f-footer-link-text];
} }
a:hover { a:hover {

View File

@@ -29,6 +29,19 @@
--border1-dark: hsl(var(--brand-hue) 40% 70%); --border1-dark: hsl(var(--brand-hue) 40% 70%);
--brand-dim: hsl(var(--brand-hue) calc(var(--brand-saturation) / 1.25) calc(var(--brand-lightness) / 1.25)); --brand-dim: hsl(var(--brand-hue) calc(var(--brand-saturation) / 1.25) calc(var(--brand-lightness) / 1.25));
--brand-50: hsl(var(--brand-hue) 100% 97%);
--brand-100: hsl(var(--brand-hue) 100% 93%);
--brand-200: hsl(var(--brand-hue) 100% 85%);
--brand-300: hsl(var(--brand-hue) 100% 75%);
--brand-400: hsl(var(--brand-hue) 100% 62%);
--brand-500: hsl(var(--brand-hue) 100% 50%);
--brand-600: hsl(var(--brand-hue) 100% 42%);
--brand-700: hsl(var(--brand-hue) 100% 35%);
--brand-800: hsl(var(--brand-hue) 100% 28%);
--brand-900: hsl(var(--brand-hue) 100% 20%);
--link-color: hsl(190 100% 30%);
} }
:root { :root {
@@ -44,9 +57,15 @@
--f-header-2: var(--text1-light); --f-header-2: var(--text1-light);
--f-header-items: (var(--text2-light)); --f-header-items: (var(--text2-light));
--gray-500: hsl(var(--brand-hue) 0% 97%);
--link-color-aaa: hsl(var(--brand-hue) 100% 28%);
/* Kontrast: ~7.1:1 - spełnia AAA */
--link-hover-aaa: hsl(var(--brand-hue) 100% 20%);
--f-footer-background: var(--gray-500);
--f-footer-link-text: var(--link-color-aaa);
--f-link-text: var(--brand-dim); --f-link-text: var(--link-color);
/* var(--brand-light); */ /* var(--brand-light); */
--f-link-text-hover: var(--f-text2-light); --f-link-text-hover: var(--f-text2-light);
@@ -54,7 +73,7 @@
--btn-background: var(--surface2-light); --btn-background: var(--surface2-light);
--btn-text: var(--text1-light); --btn-text: var(--text1-light);
--f-background-o: var(--surface4-light); --f-background-o: var(--surface3-light);
--btn-outline-background: transparent; --btn-outline-background: transparent;
--btn-outline-border: var(--border1-light); --btn-outline-border: var(--border1-light);
@@ -66,7 +85,8 @@
--f-input-border: var(--surface1-light); --f-input-border: var(--surface1-light);
--f-offers-border: var(--surface4-light); --f-offers-border: var(--surface4-light);
--f-offers-price: var(--brand-light); --f-offers-price: var(--brand-700);
/* var(--brand-light); */
--f-offers-popular: var(--brand-light); --f-offers-popular: var(--brand-light);
--f-offers-popular-bg: color-mix(in srgb, var(--f-offers-popular) 22%, transparent); --f-offers-popular-bg: color-mix(in srgb, var(--f-offers-popular) 22%, transparent);
@@ -133,6 +153,9 @@
--f-autocomplete-hover-bg: var(--surface3-dark); --f-autocomplete-hover-bg: var(--surface3-dark);
--f-autocomplete-hover-text: var(--text1-dark); --f-autocomplete-hover-text: var(--text1-dark);
--f-footer-background: var(--surface2-dark);
--f-footer-link-text: var(--brand-dark);
} }
/* Body */ /* Body */