aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--src/components/ParkMap.astro50
1 files changed, 47 insertions, 3 deletions
diff --git a/src/components/ParkMap.astro b/src/components/ParkMap.astro
index 3cccc7c..47dae97 100644
--- a/src/components/ParkMap.astro
+++ b/src/components/ParkMap.astro
@@ -62,7 +62,24 @@
background: #f1f5f9;
}
:global(.leaflet-overlay-pane path.park-selected) {
- filter: drop-shadow(0 0 5px rgba(230, 81, 0, 0.95));
+ filter: drop-shadow(0 0 6px rgba(230, 81, 0, 0.95));
+ animation: park-selected-pulse 1.2s ease-in-out infinite;
+ }
+ @keyframes park-selected-pulse {
+ 0%,
+ 100% {
+ fill-opacity: 0.85;
+ stroke-opacity: 1;
+ }
+ 50% {
+ fill-opacity: 0.2;
+ stroke-opacity: 0.35;
+ }
+ }
+ @media (prefers-reduced-motion: reduce) {
+ :global(.leaflet-overlay-pane path.park-selected) {
+ animation: none;
+ }
}
.park-map-legend {
@@ -909,6 +926,8 @@
// 拡大時だけ表示する設備アイコン(トイレ・水飲み場)
// 一覧と一致した公園のポリゴン内にだけ表示する。
const facilityLayer = L.layerGroup();
+ const facilityMarkersByName = new Map<string, any[]>();
+ const playMarkersByName = new Map<string, any[]>();
layersByName.forEach((lyr, name) => {
const p = parkDataByName.get(name);
if (!p) return;
@@ -947,7 +966,7 @@
}
if (!icons.length) return;
const center = centerOfLayer(lyr);
- L.marker([center.lat, center.lng], {
+ const marker = L.marker([center.lat, center.lng], {
icon: L.divIcon({
className: "park-fac-markers",
html: `<span class="park-fac-list">${icons.join("")}</span>`,
@@ -957,6 +976,9 @@
riseOnHover: false,
interactive: false,
}).addTo(facilityLayer);
+ const list = facilityMarkersByName.get(name) || [];
+ list.push(marker);
+ facilityMarkersByName.set(name, list);
});
// 拡大時だけ表示する遊具アイコン。
@@ -1006,7 +1028,7 @@
}
if (!icons.length) return;
const center = centerOfLayer(lyr);
- L.marker([center.lat, center.lng], {
+ const marker = L.marker([center.lat, center.lng], {
icon: L.divIcon({
className: "park-play-markers",
html: `<span class="park-play-list">${icons.join("")}</span>`,
@@ -1016,8 +1038,27 @@
riseOnHover: false,
interactive: false,
}).addTo(playLayer);
+ const list = playMarkersByName.get(name) || [];
+ list.push(marker);
+ playMarkersByName.set(name, list);
});
+ // フィルタ中は、該当しない公園の設備・遊具アイコンを隠す
+ const applyIconFilter = (names: Set<string> | null) => {
+ const toggle = (markersByName: Map<string, any[]>, layer: any) => {
+ markersByName.forEach((markers, name) => {
+ const show = !names || names.has(name);
+ markers.forEach((marker) => {
+ const has = layer.hasLayer(marker);
+ if (show && !has) layer.addLayer(marker);
+ else if (!show && has) layer.removeLayer(marker);
+ });
+ });
+ };
+ toggle(facilityMarkersByName, facilityLayer);
+ toggle(playMarkersByName, playLayer);
+ };
+
const updateFacilities = () => {
if (map.getZoom() >= 16) {
if (!map.hasLayer(facilityLayer)) facilityLayer.addTo(map);
@@ -1055,6 +1096,7 @@
// 1つの公園だけを強調表示にする(ほかは薄くする)
const highlightOnly = (name: string) => {
+ applyIconFilter(new Set([name]));
allLayers.forEach((lyr) => {
const parkName = lyr._parkName || "";
if (parkName === name) {
@@ -1165,6 +1207,7 @@
facilityMarkers.forEach(({ layer }) => {
setFacilityOpacity(layer, true);
});
+ applyIconFilter(new Set(names));
return;
}
@@ -1205,6 +1248,7 @@
facilityMarkers.forEach(({ name, layer }) => {
setFacilityOpacity(layer, !active || names.has(name));
});
+ applyIconFilter(active ? new Set(names) : null);
});
// 現在地表示(ボタン操作時のみ取得)