aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorYasutake Yohei <61961825+yasutakeyohei@users.noreply.github.com>2026-11-06 22:49:51 +0900
committerYasutake Yohei <61961825+yasutakeyohei@users.noreply.github.com>2026-11-06 22:49:51 +0900
commitf167d302249473cb6d643a3282559fbb10bada8c (patch)
treee20bb7e034c8e88eb738481e42b9a486a72636a3
parent5dfc584c9dcb89d4c00300b261107aa08c77e2e2 (diff)
parks: 地図の名前表示と表スクロール、選択バーを調整
公共施設の名前をズーム15から表示し、切替時のみ処理するようにした。表は枠内で該当行を先頭にスクロール。選択バーのリンクを「Gマップ」「経路」にし、一覧で見るを削除。全公園の点滅、枠線の細線化、閉じるボタンの折りたたみ、挿入アニメーションを調整。
-rw-r--r--src/components/ParkMap.astro95
-rw-r--r--src/components/ParksTable.astro4
2 files changed, 68 insertions, 31 deletions
diff --git a/src/components/ParkMap.astro b/src/components/ParkMap.astro
index 07d54bb..c67b4b3 100644
--- a/src/components/ParkMap.astro
+++ b/src/components/ParkMap.astro
@@ -335,9 +335,40 @@
font-size: 0.72rem;
}
:global(.park-map-selected a) {
+ display: inline-flex;
+ align-items: center;
+ gap: 0.2rem;
color: #0b57d0;
white-space: nowrap;
}
+ :global(.park-map-selected:not([hidden])) {
+ animation: park-map-selected-in 0.45s ease-out;
+ }
+ @keyframes park-map-selected-in {
+ 0% {
+ opacity: 0;
+ transform: translateY(14px) scale(0.95);
+ box-shadow: 0 0 0 6px rgba(27, 94, 32, 0.45);
+ }
+ 100% {
+ opacity: 1;
+ transform: none;
+ box-shadow: 0 1px 4px rgba(0, 0, 0, 0.18);
+ }
+ }
+ @media (prefers-reduced-motion: reduce) {
+ :global(.park-map-selected:not([hidden])) {
+ animation: none;
+ }
+ }
+ :global(.park-map-link-ico) {
+ font-size: 1em;
+ line-height: 1;
+ }
+ /* 公共施設の名前を遊具アイコンより下に置く */
+ :global(.leaflet-tooltip-pane) {
+ z-index: 590 !important;
+ }
.swatch-fac {
display: inline-flex;
align-items: center;
@@ -568,7 +599,7 @@
const MATCHED_STYLE = {
color: "#2e7d32",
- weight: 2,
+ weight: 1.5,
fillColor: "#66bb6a",
fillOpacity: 0.35,
};
@@ -587,13 +618,13 @@
};
const SELECTED_STYLE = {
color: "#1b5e20",
- weight: 4,
+ weight: 3,
fillColor: "#69f0ae",
fillOpacity: 0.75,
};
const NEARBY_STYLE = {
color: "#2e7d32",
- weight: 2,
+ weight: 1.5,
fillColor: "#66bb6a",
fillOpacity: 0.35,
};
@@ -606,7 +637,7 @@
};
const NEARBY_SELECTED_STYLE = {
color: "#1b5e20",
- weight: 4,
+ weight: 3,
fillColor: "#69f0ae",
fillOpacity: 0.75,
};
@@ -745,9 +776,8 @@
filterClose.className = "park-map-filter-close";
filterClose.textContent = "閉じる";
filterClose.addEventListener("click", () => {
- document
- .querySelector<HTMLButtonElement>(".park-map-fullscreen button")
- ?.click();
+ filterBody.hidden = true;
+ if (filterCaret) filterCaret.textContent = "▾";
});
filterFooter.appendChild(filterClose);
filterPanel.append(filterToggle, filterBody, filterFooter);
@@ -898,7 +928,6 @@
let selectedNameEl: HTMLElement | null = null;
let selectedMapsLink: HTMLAnchorElement | null = null;
let selectedRouteLink: HTMLAnchorElement | null = null;
- let selectedTableLink: HTMLAnchorElement | null = null;
let selectedNoteEl: HTMLElement | null = null;
let selectedOwnerEl: HTMLElement | null = null;
@@ -909,8 +938,7 @@
owner = "",
mapsQuery = "",
) => {
- if (!selectedBar || !selectedNameEl || !selectedMapsLink || !selectedTableLink)
- return;
+ if (!selectedBar || !selectedNameEl || !selectedMapsLink) return;
selectedNameEl.textContent = ourName;
selectedNameEl.title =
osmName && osmName !== ourName ? `OSM: ${osmName}` : "";
@@ -934,8 +962,6 @@
if (selectedRouteLink) {
selectedRouteLink.href = `https://www.google.com/maps/dir/?api=1&destination=${encodeURIComponent(destination)}&travelmode=walking`;
}
- selectedTableLink.dataset.parkRow = encodeURIComponent(ourName);
- selectedTableLink.hidden = !listed;
if (selectedNoteEl) selectedNoteEl.hidden = listed;
if (selectedOwnerEl) {
selectedOwnerEl.textContent = owner ? ownerLabel(owner) : "";
@@ -952,23 +978,14 @@
'<span class="park-map-selected-name"></span>' +
'<span class="park-map-selected-owner" hidden></span>' +
'<span class="park-map-selected-note" hidden>一覧にない緑地・公園</span>' +
- '<a data-park-maps-link href="#" target="_blank" rel="noopener">Googleマップ</a>' +
- '<a data-park-route-link href="#" target="_blank" rel="noopener">徒歩の経路</a>' +
- '<a data-park-table-link href="#">一覧で見る</a>';
+ '<a data-park-maps-link href="#" target="_blank" rel="noopener"><span class="park-map-link-ico" aria-hidden="true">🗺</span>Gマップ</a>' +
+ '<a data-park-route-link href="#" target="_blank" rel="noopener"><span class="park-map-link-ico" aria-hidden="true">🚶</span>経路</a>';
selectedBar = box;
selectedNameEl = box.querySelector<HTMLElement>(".park-map-selected-name");
selectedMapsLink = box.querySelector<HTMLAnchorElement>("[data-park-maps-link]");
selectedRouteLink = box.querySelector<HTMLAnchorElement>("[data-park-route-link]");
- selectedTableLink = box.querySelector<HTMLAnchorElement>("[data-park-table-link]");
selectedNoteEl = box.querySelector<HTMLElement>(".park-map-selected-note");
selectedOwnerEl = box.querySelector<HTMLElement>(".park-map-selected-owner");
- selectedTableLink?.addEventListener("click", (ev: Event) => {
- ev.preventDefault();
- const name = decodeURIComponent(
- (selectedTableLink as HTMLElement).dataset.parkRow || "",
- );
- if (name) filterName(name, true);
- });
L.DomEvent.disableClickPropagation(box);
return box;
},
@@ -1320,6 +1337,7 @@
toggle(playMarkersByName, playLayer);
};
+ let facilityLabelsShown = false;
const updateFacilities = () => {
if (map.getZoom() >= 17) {
if (!map.hasLayer(facilityLayer)) facilityLayer.addTo(map);
@@ -1336,16 +1354,32 @@
} else if (map.hasLayer(parkNameLayer)) {
map.removeLayer(parkNameLayer);
}
- // 公共施設の名前は少し引いたズームから表示する
- const showFacilityLabels = map.getZoom() >= 14;
- facilityMarkers.forEach(({ layer }) => {
- if (showFacilityLabels) layer.openTooltip();
- else layer.closeTooltip();
- });
+ // 公共施設の名前はもう一段ズームしたときだけ表示する(切替時のみ実行)
+ const showFacilityLabels = map.getZoom() >= 15;
+ if (showFacilityLabels !== facilityLabelsShown) {
+ facilityLabelsShown = showFacilityLabels;
+ facilityMarkers.forEach(({ layer }) => {
+ if (showFacilityLabels) layer.openTooltip();
+ else layer.closeTooltip();
+ });
+ }
};
map.on("zoomend", updateFacilities);
updateFacilities();
+ // フィルタがないときは、すべての公園を点滅させる
+ allLayers.forEach((lyr) => {
+ const n = lyr._parkName || "";
+ lyr.setStyle(n ? MATCHED_STYLE : UNMATCHED_STYLE);
+ markSelected(lyr, false);
+ markBlink(lyr, true);
+ });
+ nearbyEntries.forEach(({ layer }) => {
+ layer.setStyle(nearbyBaseStyle(layer));
+ markSelected(layer, false);
+ markBlink(layer, true);
+ });
+
let userInteracted = false;
map.on("zoomstart dragstart", () => {
userInteracted = true;
@@ -1494,7 +1528,7 @@
if (!active) {
lyr.setStyle(name ? MATCHED_STYLE : UNMATCHED_STYLE);
markSelected(lyr, false);
- markBlink(lyr, Boolean(name));
+ markBlink(lyr, true);
return;
}
if (name && names.has(name)) {
@@ -1513,6 +1547,7 @@
if (!active) {
lyr.setStyle(nearbyBaseStyle(lyr));
markSelected(lyr, false);
+ markBlink(lyr, true);
return;
}
if (name && names.has(name)) {
diff --git a/src/components/ParksTable.astro b/src/components/ParksTable.astro
index 2141eac..4918b2c 100644
--- a/src/components/ParksTable.astro
+++ b/src/components/ParksTable.astro
@@ -779,9 +779,11 @@ function isUnconfirmed(p: Park): boolean {
const scrollRowIntoView = (row: HTMLElement) => {
const scroller = root.querySelector<HTMLElement>(".parks-scroll");
if (!scroller) return;
+ const thead = scroller.querySelector("thead");
+ const headH = thead ? thead.getBoundingClientRect().height : 0;
const rowRect = row.getBoundingClientRect();
const scRect = scroller.getBoundingClientRect();
- const delta = rowRect.top - scRect.top - scRect.height / 2 + rowRect.height / 2;
+ const delta = rowRect.top - scRect.top - headH - 2;
scroller.scrollTo({ top: scroller.scrollTop + delta, behavior: "smooth" });
};