aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/components/FacilitiesTable.astro70
-rw-r--r--src/components/ParkMap.astro446
-rw-r--r--src/components/ParkMapHelp.astro111
-rw-r--r--src/components/ParksFilters.astro184
-rw-r--r--src/components/ParksTable.astro260
-rw-r--r--src/content/docs/kodaira-data/parks.mdx90
-rw-r--r--src/data/kodaira-nearby-facilities.json306
-rw-r--r--src/data/kodaira-nearby-parks.json2
-rw-r--r--src/data/park-icons.ts15
-rw-r--r--src/data/parks-rows.ts141
-rw-r--r--src/styles/custom.css62
11 files changed, 1434 insertions, 253 deletions
diff --git a/src/components/FacilitiesTable.astro b/src/components/FacilitiesTable.astro
index 2974581..797bb1a 100644
--- a/src/components/FacilitiesTable.astro
+++ b/src/components/FacilitiesTable.astro
@@ -1,7 +1,9 @@
---
-// 地域センター・公民館・図書館・市役所支所・文化施設の一覧。
+// 地域センター・公民館・児童館・図書館・市役所支所・文化施設の一覧。
+// 小平市の施設に加えて、市境500m以内の市外施設(図書館・公民館・児童館)も表示する。
// トイレは市の公共施設として基本的に利用できる。給水は公式ページに明記が少ないため「未確認」が多い。
import facilitiesData from "@/data/kodaira-facilities.json";
+import nearbyFacilitiesData from "@/data/kodaira-nearby-facilities.json";
type Facility = {
name: string;
@@ -13,12 +15,32 @@ type Facility = {
water: string;
note: string;
source: string;
+ nearby?: boolean;
+ city?: string;
+ distance_m?: number;
};
-const facilities = facilitiesData as Facility[];
-const types = ["地域センター", "公民館", "図書館", "市役所支所", "文化施設"];
-const mapsUrl = (name: string) =>
- `https://www.google.com/maps/search/?api=1&query=${encodeURIComponent(`小平市${name}`)}`;
+const facilities = [
+ ...(facilitiesData as Facility[]),
+ ...(nearbyFacilitiesData as Facility[]),
+];
+const types = [
+ "地域センター",
+ "公民館",
+ "児童館",
+ "図書館",
+ "市役所支所",
+ "文化施設",
+];
+const mapsUrl = (f: Facility) => {
+ // 市外の施設は「小平市」を付けない。名前が市名を含む場合は二重にしない。
+ const query = f.nearby
+ ? f.city && !f.name.includes(f.city)
+ ? `${f.city}${f.name}`
+ : f.name
+ : `小平市${f.name}`;
+ return `https://www.google.com/maps/search/?api=1&query=${encodeURIComponent(query)}`;
+};
---
<div class="facilities" data-fac-root>
@@ -60,7 +82,7 @@ const mapsUrl = (name: string) =>
data-type={f.type}
data-toilet={f.toilet || ""}
data-water={f.water || ""}
- data-search={`${f.name} ${f.type} ${f.address} ${f.note}`.toLowerCase()}
+ data-search={`${f.name} ${f.type} ${f.address} ${f.city || ""} ${f.note}`.toLowerCase()}
>
<td>
{f.source ? (
@@ -68,10 +90,13 @@ const mapsUrl = (name: string) =>
) : (
f.name
)}
+ {f.nearby ? (
+ <span class="fac-nearby" title="小平市外の施設">市外</span>
+ ) : null}
</td>
<td>{f.type}</td>
<td>
- <a href={mapsUrl(f.name)} target="_blank" rel="noopener">
+ <a href={mapsUrl(f)} target="_blank" rel="noopener">
{f.address || "—"}
</a>
</td>
@@ -96,9 +121,12 @@ const mapsUrl = (name: string) =>
</table>
</div>
- <p class="fac-note">
- トイレは市の公共施設として基本的に利用できます(○)。給水は公式ページに明記が少ないため「未確認」が多いです。最新の情報は各施設の公式ページで確認してください。地図の位置は住所・名称からの概略です。
- </p>
+ <details class="fac-help">
+ <summary>設備情報について</summary>
+ <p class="fac-note">
+ 小平市の施設は、公共施設のためトイレを利用できます(○)。市外の近隣施設は情報がないため「未確認」としています。給水は公式ページに明記が少ないため「未確認」が多いです。最新の情報は各施設の公式ページで確認してください。市外施設の情報はOpenStreetMapによるもので、地図の位置は住所・名称からの概略です。
+ </p>
+ </details>
</div>
<script>
@@ -178,9 +206,29 @@ const mapsUrl = (name: string) =>
.fac-status.is-no {
color: #b71c1c;
}
- .fac-note {
+ .fac-nearby {
+ display: inline-block;
+ margin-left: 0.35rem;
+ padding: 0.02rem 0.35rem;
+ border: 1px solid currentColor;
+ border-radius: 999px;
+ color: #6d4c41;
+ font-size: 0.7rem;
+ font-weight: 600;
+ line-height: 1.5;
+ vertical-align: 0.08em;
+ white-space: nowrap;
+ }
+ .fac-help {
margin-top: 0.5rem;
color: var(--sl-color-gray-2);
font-size: 0.82em;
}
+ .fac-help summary {
+ cursor: pointer;
+ color: var(--sl-color-text-accent);
+ }
+ .fac-note {
+ margin: 0.35rem 0 0;
+ }
</style>
diff --git a/src/components/ParkMap.astro b/src/components/ParkMap.astro
index 1c75bee..e4f226b 100644
--- a/src/components/ParkMap.astro
+++ b/src/components/ParkMap.astro
@@ -10,22 +10,6 @@
role="region"
aria-label="小平市の公園の位置(OpenStreetMap)"
></div>
- <div class="park-map-legend" aria-hidden="true">
- <span><i class="swatch swatch-matched"></i>一覧と一致</span>
- <span><i class="swatch swatch-unmatched"></i>一覧にない公園・緑地</span>
- <span><i class="swatch swatch-nearby"></i>市外の近い公園(500m以内)</span>
- <span><i class="swatch swatch-facility"></i>公共施設</span>
- <span><i class="swatch swatch-boundary"></i>小平市の境界</span>
- <span><i class="swatch-fac swatch-fac-toilet">WC</i>トイレ</span>
- <span><i class="swatch-fac swatch-fac-water"><svg viewBox="0 0 24 24" width="10" height="10" aria-hidden="true"><path fill="currentColor" d="M12 2.7c-3.4 4.2-6 8.1-6 11.3a6 6 0 0 0 12 0c0-3.2-2.6-7.1-6-11.3z" /></svg></i>水飲み場(拡大時)</span>
- </div>
- <p class="park-map-note">
- 公園の範囲を赤で表示しています。地図を拡大すると見やすくなります。PCでは地図上でスクロールするとズームできます。市外の近い公園と公共施設は別レイヤーで表示し、右上のレイヤ切替でON/OFFできます。トイレと水飲み場のアイコンは、地図を拡大すると表示されます。OpenStreetMapに公園として登録されている範囲を表示しているため、すべての公園を網羅しているわけではありません。現在地は端末内でのみ利用し、サーバーには送信しません。地図データ © <a
- href="https://www.openstreetmap.org/copyright"
- target="_blank"
- rel="noopener">OpenStreetMap</a
- > contributors
- </p>
<p class="park-map-locate-status" data-locate-status hidden></p>
</div>
@@ -94,6 +78,10 @@
background: #8e24aa;
border-radius: 50%;
}
+ .swatch-facility-nearby {
+ background: #fb8c00;
+ border-radius: 50%;
+ }
.swatch-boundary {
height: 0;
border-top: 4px solid #6a1b9a;
@@ -106,18 +94,46 @@
font-size: 0.8rem;
}
:global(.park-locate) {
- width: 34px;
- height: 34px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 40px;
+ height: 40px;
+ padding: 0;
border: 0;
+ border-radius: 50%;
background: #fff;
color: #1e88e5;
- font-size: 20px;
- line-height: 1;
+ box-shadow: 0 1px 4px rgba(0, 0, 0, 0.35);
cursor: pointer;
}
:global(.park-locate:hover) {
background: #f0f7ff;
}
+ :global(.park-locate.is-tracking) {
+ background: #1e88e5;
+ color: #fff;
+ animation: park-locate-pulse 1.8s infinite;
+ }
+ :global(.park-locate.is-tracking:hover) {
+ background: #1565c0;
+ }
+ @keyframes park-locate-pulse {
+ 0% {
+ box-shadow: 0 0 0 0 rgba(30, 136, 229, 0.45);
+ }
+ 70% {
+ box-shadow: 0 0 0 9px rgba(30, 136, 229, 0);
+ }
+ 100% {
+ box-shadow: 0 0 0 0 rgba(30, 136, 229, 0);
+ }
+ }
+ :global(.park-locate svg) {
+ display: block;
+ width: 20px;
+ height: 20px;
+ }
.park-map-note {
margin-top: 0.4rem;
color: var(--sl-color-gray-2);
@@ -218,6 +234,122 @@
:global(.park-fac svg) {
display: block;
}
+ :global(.park-facility-marker) {
+ background: none;
+ border: 0;
+ }
+ :global(.park-facility-emoji) {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ box-sizing: border-box;
+ width: 22px;
+ height: 22px;
+ border: 2px solid #8e24aa;
+ border-radius: 50%;
+ background: #fff;
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
+ font-size: 13px;
+ line-height: 1;
+ }
+ :global(.park-facility-marker.is-nearby .park-facility-emoji) {
+ border-color: #fb8c00;
+ }
+ :global(.park-play-markers),
+ :global(.park-play-list) {
+ pointer-events: none;
+ }
+ :global(.park-play-list) {
+ display: inline-flex;
+ gap: 2px;
+ transform: translate(-50%, -50%) translateY(-24px);
+ }
+ :global(.park-play) {
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ width: 24px;
+ height: 24px;
+ border: 1px solid currentColor;
+ border-radius: 50%;
+ background: #fff;
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25);
+ font-size: 9px;
+ font-weight: 700;
+ line-height: 1;
+ }
+ :global(.park-play-plane) {
+ color: #c62828;
+ }
+ :global(.park-play-swing) {
+ color: #ef6c00;
+ }
+ :global(.park-play-seesaw) {
+ color: #6d4c41;
+ }
+ :global(.park-play-spring) {
+ color: #d81b60;
+ }
+ :global(.park-play-slide) {
+ color: #2e7d32;
+ }
+ :global(.park-play-jungle) {
+ color: #6a1b9a;
+ }
+ :global(.park-play-sand) {
+ color: #3e2723;
+ }
+ :global(.park-play-sand svg *) {
+ vector-effect: non-scaling-stroke;
+ }
+ :global(.park-play-complex) {
+ color: #0277bd;
+ }
+ :global(.park-play-ball) {
+ color: #1b5e20;
+ }
+ :global(.park-play-rope) {
+ color: #00838f;
+ }
+ :global(.park-locate-marker) {
+ border: 0;
+ background: none;
+ }
+ :global(.park-locate-arrow) {
+ display: block;
+ transform-origin: 50% 50%;
+ filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.35));
+ }
+ .park-map-help {
+ margin-top: 0.4rem;
+ }
+ .park-map-help summary {
+ cursor: pointer;
+ color: var(--sl-color-text-accent);
+ font-size: 0.85rem;
+ }
+ .park-play-legend {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 0.35rem 0.8rem;
+ margin: 0.5rem 0 0;
+ color: var(--sl-color-gray-2);
+ font-size: 0.78rem;
+ }
+ .park-play-legend-item {
+ display: inline-flex;
+ align-items: center;
+ gap: 0.3rem;
+ }
+ :global(.park-play svg) {
+ display: block;
+ width: 100%;
+ height: 100%;
+ }
+ :global(.park-play-swing svg) {
+ width: 70%;
+ height: 70%;
+ }
/* StarlightのMarkdown余白ルールがLeafletの各ペインに margin-top:1rem を
付けて地図を下へずらすため、地図内のペインは余白なしにする。 */
.park-map :global(.leaflet-pane) {
@@ -252,6 +384,8 @@
import boundary from "@/data/kodaira-boundary.json";
import nearbyData from "@/data/kodaira-nearby-parks.json";
import facilities from "@/data/kodaira-facilities.json";
+ import nearbyFacilities from "@/data/kodaira-nearby-facilities.json";
+ import { PARK_ICONS } from "@/data/park-icons";
import parks from "@/data/kodaira-parks.json";
const MATCHED_STYLE = {
@@ -285,6 +419,13 @@
fillColor: "#42a5f5",
fillOpacity: 0.25,
};
+ const NEARBY_POINT_STYLE = {
+ radius: 7,
+ color: "#0d47a1",
+ weight: 2,
+ fillColor: "#42a5f5",
+ fillOpacity: 0.85,
+ };
const NEARBY_SELECTED_STYLE = {
color: "#0d47a1",
weight: 3,
@@ -365,7 +506,9 @@
if (name) nearbyInfoByName.set(name, p);
});
const nearbyMapsQuery = (name: string, city = "") =>
- name ? (city ? `${city}${name}` : name) : "";
+ name ? (city && !name.includes(city) ? `${city}${name}` : name) : "";
+ const nearbyBaseStyle = (lyr: any) =>
+ lyr._isPoint ? NEARBY_POINT_STYLE : NEARBY_STYLE;
const parkDataByName = new Map<string, any>();
(parks as any[]).forEach((p) => parkDataByName.set(p["公園名"], p));
const ownerByName = new Map<string, string>();
@@ -536,12 +679,17 @@
// 市外の近い公園(500m以内)は別レイヤーにする。
// 小平市内の公園と同じく、クリックで一覧を絞り込み、左下に情報を表示する。
const nearbyLayer = L.geoJSON(nearbyData as any, {
- style: NEARBY_STYLE,
+ // 範囲が取得できない公園は点(丸)で表示する。
+ pointToLayer: (_feature: any, latlng: any) =>
+ L.circleMarker(latlng, NEARBY_POINT_STYLE),
+ style: (feature: any) =>
+ feature?.geometry?.type === "Point" ? NEARBY_POINT_STYLE : NEARBY_STYLE,
onEachFeature: (feature: any, lyr: any) => {
const p = feature.properties || {};
const name = String(p.name || "").trim();
const city = String(p.city || "").trim();
const key = `${p.osm_type || ""}/${p.osm_id || ""}`;
+ lyr._isPoint = feature.geometry?.type === "Point";
if (name) nearbyEntries.push({ name, layer: lyr, city, key });
lyr.on("click", (ev: any) => {
if (ev?.originalEvent) L.DomEvent.stopPropagation(ev.originalEvent);
@@ -552,35 +700,51 @@
},
}).addTo(map);
- // 地域センター・公民館・図書館・市役所支所。
+ // 地域センター・公民館・図書館・市役所支所・文化施設。
+ // 市外の近隣施設はオレンジで表示する。
const publicFacilityLayer = L.layerGroup();
- (facilities as any[]).forEach((f) => {
- if (f.lat == null || f.lon == null) return;
- L.circleMarker([f.lat, f.lon], {
- radius: 6,
- color: "#4a148c",
- weight: 1.5,
- fillColor: "#8e24aa",
- fillOpacity: 0.85,
- })
- .bindPopup(
- `<strong>${f.name}</strong><br>${f.type}<br>${f.hours || ""}${f.closed ? `<br>休: ${f.closed}` : ""}<br>トイレ: ${f.toilet || "未確認"} / 給水: ${f.water || "未確認"}`,
- )
- .addTo(publicFacilityLayer);
- });
+ const facilityMarkers: { name: string; layer: any }[] = [];
+ const FACILITY_ICON: Record<string, string> = {
+ 地域センター: "📍",
+ 公民館: "🏛",
+ 児童館: "🧒",
+ 図書館: "📚",
+ 市役所支所: "🏢",
+ 文化施設: "🎭",
+ };
+ const setFacilityOpacity = (layer: any, show: boolean) => {
+ if (typeof layer.setOpacity === "function") {
+ layer.setOpacity(show ? 1 : 0.2);
+ } else if (typeof layer.setStyle === "function") {
+ layer.setStyle({
+ opacity: show ? 1 : 0.15,
+ fillOpacity: show ? 0.85 : 0.1,
+ });
+ }
+ };
+ const addFacilities = (list: any[], nearby: boolean) => {
+ list.forEach((f) => {
+ if (f.lat == null || f.lon == null) return;
+ const icon = FACILITY_ICON[f.type] || "";
+ const marker = L.marker([f.lat, f.lon], {
+ icon: L.divIcon({
+ className: `park-facility-marker${nearby ? " is-nearby" : ""}`,
+ html: `<span class="park-facility-emoji">${icon || "🏢"}</span>`,
+ iconSize: [22, 22],
+ iconAnchor: [11, 11],
+ }),
+ })
+ .bindPopup(
+ `<strong>${icon} ${f.name}</strong>${nearby ? "(市外)" : ""}<br>${f.type}<br>${f.hours || ""}${f.closed ? `<br>休: ${f.closed}` : ""}<br>トイレ: ${f.toilet || "未確認"} / 給水: ${f.water || "未確認"}`,
+ )
+ .addTo(publicFacilityLayer);
+ facilityMarkers.push({ name: String(f.name || ""), layer: marker });
+ });
+ };
+ addFacilities(facilities as any[], false);
+ addFacilities(nearbyFacilities as any[], true);
publicFacilityLayer.addTo(map);
- L.control
- .layers(
- null,
- {
- "市外の近い公園(500m以内)": nearbyLayer,
- "公共施設": publicFacilityLayer,
- },
- { collapsed: false, position: "topright" },
- )
- .addTo(map);
-
// 拡大時だけ表示する設備アイコン(トイレ・水飲み場)
// 一覧と一致した公園のポリゴン内にだけ表示する。
const facilityLayer = L.layerGroup();
@@ -612,12 +776,76 @@
}).addTo(facilityLayer);
});
+ // 拡大時だけ表示する遊具アイコン。
+ // 公園ポリゴンの中心に、遊具の種類を絵アイコンで表示する。
+ const PLAY_DEFS = [
+ { tokens: ["ヒコーキ", "飛行機"], key: "airplane", title: PARK_ICONS.airplane.title, cls: "park-play-plane", icon: PARK_ICONS.airplane.svg },
+ { tokens: ["ジャングル"], key: "climbing", title: PARK_ICONS.climbing.title, cls: "park-play-jungle", icon: PARK_ICONS.climbing.svg },
+ { tokens: ["ブランコ"], key: "swing", title: PARK_ICONS.swing.title, cls: "park-play-swing", icon: PARK_ICONS.swing.svg },
+ { tokens: ["シーソー"], key: "seesaw", title: PARK_ICONS.teeter.title, cls: "park-play-seesaw", icon: PARK_ICONS.teeter.svg },
+ { tokens: ["スプリング"], key: "spring", title: PARK_ICONS.spring.title, cls: "park-play-spring", icon: PARK_ICONS.spring.svg },
+ { tokens: ["滑り台", "滑台"], key: "slide", title: PARK_ICONS.slide.title, cls: "park-play-slide", icon: PARK_ICONS.slide.svg },
+ { tokens: ["ロープウェイ"], key: "flyingfox", title: PARK_ICONS.flyingfox.title, cls: "park-play-rope", icon: PARK_ICONS.flyingfox.svg },
+ { tokens: ["砂場"], key: "sand", title: PARK_ICONS.sand.title, cls: "park-play-sand", icon: PARK_ICONS.sand.svg },
+ { tokens: ["複合遊具"], key: "playground", title: PARK_ICONS.playground.title, cls: "park-play-complex", icon: PARK_ICONS.playground.svg },
+ { tokens: [], key: "ball", title: PARK_ICONS.ball.title, cls: "park-play-ball", icon: PARK_ICONS.ball.svg },
+ ];
+ const playLegend = document.querySelector<HTMLElement>("[data-play-legend]");
+ if (playLegend) {
+ playLegend.innerHTML = PLAY_DEFS.map(
+ (def) =>
+ `<span class="park-play-legend-item"><span class="park-play ${def.cls}" aria-hidden="true">${def.icon}</span>${def.title}</span>`,
+ ).join("");
+ }
+ const playLayer = L.layerGroup();
+ layersByName.forEach((lyr, name) => {
+ const p = parkDataByName.get(name);
+ if (!p) return;
+ const text = (p["遊具"] || "").trim();
+ const ballText = (p["ボール遊び"] || "").trim();
+ const hasBall = Boolean(ballText && ballText !== "禁止");
+ if (!text && !hasBall) return;
+ const seen = new Set<string>();
+ const icons: string[] = [];
+ for (const def of PLAY_DEFS) {
+ const matched =
+ def.key === "ball"
+ ? hasBall
+ : def.tokens.some((token) => text.includes(token));
+ if (!matched) continue;
+ if (seen.has(def.key)) continue;
+ // ヒコーキジャングルはジャングルジムの一種なので、飛があればジは出さない。
+ if (def.key === "climbing" && seen.has("airplane")) continue;
+ seen.add(def.key);
+ icons.push(
+ `<span class="park-play ${def.cls}" title="${def.title}" aria-label="${def.title}">${def.icon}</span>`,
+ );
+ }
+ if (!icons.length) return;
+ const center = lyr.getBounds().getCenter();
+ L.marker([center.lat, center.lng], {
+ icon: L.divIcon({
+ className: "park-play-markers",
+ html: `<span class="park-play-list">${icons.join("")}</span>`,
+ iconSize: null,
+ iconAnchor: [0, 0],
+ }),
+ riseOnHover: false,
+ interactive: false,
+ }).addTo(playLayer);
+ });
+
const updateFacilities = () => {
if (map.getZoom() >= 16) {
if (!map.hasLayer(facilityLayer)) facilityLayer.addTo(map);
} else if (map.hasLayer(facilityLayer)) {
map.removeLayer(facilityLayer);
}
+ if (map.getZoom() >= 17) {
+ if (!map.hasLayer(playLayer)) playLayer.addTo(map);
+ } else if (map.hasLayer(playLayer)) {
+ map.removeLayer(playLayer);
+ }
};
map.on("zoomend", updateFacilities);
updateFacilities();
@@ -646,7 +874,8 @@
if (key) {
const nearbyHit = nearbyEntries.find((entry) => entry.key === key);
if (nearbyHit) {
- map.fitBounds(nearbyHit.layer.getBounds(), { padding: [40, 40], maxZoom: 17 });
+ const group = L.featureGroup([nearbyHit.layer]);
+ map.fitBounds(group.getBounds(), { padding: [40, 40], maxZoom: 17 });
showSelected(
name,
name,
@@ -702,7 +931,6 @@
const names = new Set<string>(detail.names || []);
const active = Boolean(detail.active);
const fromMap = Boolean(detail.fromMap);
- const visible: any[] = [];
if (!fromMap && selectedBar) selectedBar.hidden = true;
@@ -718,7 +946,12 @@
}
});
nearbyEntries.forEach(({ name, layer: lyr }) => {
- lyr.setStyle(name && names.has(name) ? NEARBY_SELECTED_STYLE : NEARBY_STYLE);
+ lyr.setStyle(
+ name && names.has(name) ? NEARBY_SELECTED_STYLE : nearbyBaseStyle(lyr),
+ );
+ });
+ facilityMarkers.forEach(({ layer }) => {
+ setFacilityOpacity(layer, true);
});
return;
}
@@ -731,7 +964,6 @@
}
if (name && names.has(name)) {
lyr.setStyle(MATCHED_STYLE);
- visible.push(lyr);
} else {
lyr.setStyle(DIM_STYLE);
}
@@ -739,26 +971,23 @@
nearbyEntries.forEach(({ name, layer: lyr }) => {
if (!active) {
- lyr.setStyle(NEARBY_STYLE);
+ lyr.setStyle(nearbyBaseStyle(lyr));
return;
}
if (name && names.has(name)) {
- lyr.setStyle(NEARBY_STYLE);
- visible.push(lyr);
+ lyr.setStyle(nearbyBaseStyle(lyr));
} else {
lyr.setStyle(NEARBY_DIM_STYLE);
}
});
- if (active && visible.length && visible.length < 30) {
- const bounds = L.featureGroup(visible).getBounds();
- if (bounds.isValid()) {
- map.fitBounds(bounds, { padding: [40, 40], maxZoom: 16 });
- }
- }
+ // 公共施設のマーカーも絞り込みに合わせて表示する。
+ facilityMarkers.forEach(({ name, layer }) => {
+ setFacilityOpacity(layer, !active || names.has(name));
+ });
});
- // 現在地表示(スマホでは自動で取得を試みる)
+ // 現在地表示(ボタン操作時のみ取得)
const statusEl = document.querySelector<HTMLElement>("[data-locate-status]");
const setStatus = (msg: string) => {
if (!statusEl) return;
@@ -769,30 +998,72 @@
let locationMarker: any = null;
let accuracyCircle: any = null;
let watchId: number | null = null;
+ let tracking = false;
+ let firstFix = true;
+ let locateButton: HTMLButtonElement | null = null;
+
+ const LOCATE_ICON =
+ '<span aria-hidden="true"><svg viewBox="0 0 24 24" width="20" height="20"><path d="M12 2.2 20 21.5 12 16.8 4 21.5Z" fill="#1e88e5" stroke="#ffffff" stroke-width="2" stroke-linejoin="round"/></svg></span>';
+ const TRACKING_ICON =
+ '<span aria-hidden="true"><svg viewBox="0 0 24 24" width="20" height="20"><circle cx="12" cy="12" r="3.5" fill="currentColor"/><circle cx="12" cy="12" r="7" fill="none" stroke="currentColor" stroke-width="2"/><path d="M12 2v3M12 19v3M2 12h3M19 12h3" stroke="currentColor" stroke-width="2" stroke-linecap="round"/></svg></span>';
+
+ const updateLocateButton = () => {
+ if (!locateButton) return;
+ locateButton.classList.toggle("is-tracking", tracking);
+ locateButton.setAttribute("aria-pressed", tracking ? "true" : "false");
+ const label = tracking ? "現在地の追跡を停止" : "現在地を表示";
+ locateButton.title = label;
+ locateButton.setAttribute("aria-label", label);
+ locateButton.innerHTML = tracking ? TRACKING_ICON : LOCATE_ICON;
+ };
+
+ const stopTracking = () => {
+ if (watchId !== null) {
+ navigator.geolocation.clearWatch(watchId);
+ watchId = null;
+ }
+ tracking = false;
+ updateLocateButton();
+ };
- const locate = (center = false) => {
+ const locate = () => {
+ if (tracking) {
+ stopTracking();
+ setStatus("現在地の追跡を停止しました。");
+ return;
+ }
if (!navigator.geolocation) {
setStatus("このブラウザでは現在地を取得できません。");
return;
}
setStatus("現在地を取得しています…");
+ firstFix = true;
const onSuccess = (pos: GeolocationPosition) => {
const { latitude, longitude, accuracy } = pos.coords;
if (!locationMarker) {
- locationMarker = L.circleMarker([latitude, longitude], {
- radius: 7,
- color: "#ffffff",
- weight: 2,
- fillColor: "#1e88e5",
- fillOpacity: 1,
- }).bindPopup("現在地", { autoPan: false });
- locationMarker.on("add", () => {
- locationMarker.getElement()?.setAttribute("data-locate", "true");
+ const icon = L.divIcon({
+ className: "park-locate-marker",
+ html: '<span class="park-locate-arrow"><svg viewBox="0 0 24 24" width="24" height="24" aria-hidden="true"><path d="M12 2.2 20 21.5 12 16.8 4 21.5Z" fill="#1e88e5" stroke="#ffffff" stroke-width="2" stroke-linejoin="round"/></svg></span>',
+ iconSize: [24, 24],
+ iconAnchor: [12, 12],
});
- locationMarker.addTo(map);
+ locationMarker = L.marker([latitude, longitude], {
+ icon,
+ interactive: false,
+ keyboard: false,
+ }).addTo(map);
} else {
locationMarker.setLatLng([latitude, longitude]);
}
+ const heading =
+ typeof pos.coords.heading === "number" &&
+ Number.isFinite(pos.coords.heading)
+ ? pos.coords.heading
+ : 0;
+ const arrow = locationMarker
+ .getElement()
+ ?.querySelector<HTMLElement>(".park-locate-arrow");
+ if (arrow) arrow.style.transform = `rotate(${heading}deg)`;
if (!accuracyCircle) {
accuracyCircle = L.circle([latitude, longitude], {
radius: Math.min(accuracy, 1000),
@@ -807,13 +1078,21 @@
.setLatLng([latitude, longitude])
.setRadius(Math.min(accuracy, 1000));
}
- setStatus(`現在地を表示しています(精度 約${Math.round(accuracy)}m)。`);
- if (center) map.setView([latitude, longitude], Math.max(map.getZoom(), 15));
+ if (firstFix) {
+ map.setView([latitude, longitude], Math.max(map.getZoom(), 15));
+ firstFix = false;
+ }
+ setStatus(
+ `現在地を追跡中です(精度 約${Math.round(accuracy)}m)。もう一度押すと停止します。`,
+ );
};
const onError = () => {
setStatus("現在地を取得できませんでした。位置情報の利用を許可してください。");
+ stopTracking();
};
if (watchId !== null) navigator.geolocation.clearWatch(watchId);
+ tracking = true;
+ updateLocateButton();
watchId = navigator.geolocation.watchPosition(onSuccess, onError, {
enableHighAccuracy: true,
timeout: 10000,
@@ -823,23 +1102,22 @@
const LocateControl = L.Control.extend({
onAdd: () => {
- const btn = L.DomUtil.create("button", "leaflet-bar park-locate");
+ const btn = L.DomUtil.create("button", "park-locate") as HTMLButtonElement;
btn.setAttribute("type", "button");
- btn.title = "現在地を表示";
- btn.setAttribute("aria-label", "現在地を表示");
- btn.innerHTML = '<span aria-hidden="true">◎</span>';
+ locateButton = btn;
L.DomEvent.disableClickPropagation(btn);
- btn.addEventListener("click", () => locate(true));
+ btn.addEventListener("click", () => locate());
+ updateLocateButton();
return btn;
},
});
new LocateControl({ position: "topright" }).addTo(map);
- if (window.matchMedia("(max-width: 640px)").matches) {
- locate(true);
- }
+ // 位置情報の許可確認は、ボタン操作(ユーザー操作)のときだけ出す。
+ // ページ読み込み時に自動で watchPosition を呼ぶと、ブラウザによっては
+ // 許可ダイアログが出ずに失敗することがあるため。
window.addEventListener("pagehide", () => {
- if (watchId !== null) navigator.geolocation.clearWatch(watchId);
+ stopTracking();
});
// レイアウト確定後にサイズを再計算し、タイルを再配置する。
diff --git a/src/components/ParkMapHelp.astro b/src/components/ParkMapHelp.astro
new file mode 100644
index 0000000..26d9917
--- /dev/null
+++ b/src/components/ParkMapHelp.astro
@@ -0,0 +1,111 @@
+---
+// 地図の見方・凡例。地図と一覧表を近づけるため、一覧表の下に表示する。
+// 遊具アイコンの凡例は ParkMap.astro のスクリプトが [data-play-legend] に流し込む。
+---
+
+<details class="park-map-help">
+ <summary>地図の見方・凡例</summary>
+ <div class="park-map-legend" aria-hidden="true">
+ <span><i class="swatch swatch-matched"></i>一覧と一致</span>
+ <span><i class="swatch swatch-unmatched"></i>一覧にない公園・緑地</span>
+ <span><i class="swatch swatch-nearby"></i>市外の近い公園(500m以内)</span>
+ <span><i class="swatch swatch-facility"></i>公共施設</span>
+ <span><i class="swatch swatch-facility-nearby"></i>市外の公共施設</span>
+ <span><i class="swatch swatch-boundary"></i>小平市の境界</span>
+ <span><i class="swatch-fac swatch-fac-toilet">WC</i>トイレ</span>
+ <span><i class="swatch-fac swatch-fac-water"><svg viewBox="0 0 24 24" width="10" height="10" aria-hidden="true"><path fill="currentColor" d="M12 2.7c-3.4 4.2-6 8.1-6 11.3a6 6 0 0 0 12 0c0-3.2-2.6-7.1-6-11.3z" /></svg></i>水飲み場(拡大時)</span>
+ </div>
+ <div class="park-play-legend" data-play-legend></div>
+ <p class="park-map-note">
+ 公園の範囲を赤、市外の近い公園を青、公共施設を紫(市外はオレンジ)で表示しています。地図を拡大すると見やすくなります。PCでは地図上でスクロールするとズームできます。市外の近い公園のうち、範囲が取得できないものは丸で表示しています。トイレと水飲み場のアイコンは拡大すると表示されます。さらに拡大すると、遊具アイコン(上の凡例)が表示されます。OpenStreetMapに公園として登録されている範囲を表示しているため、すべての公園を網羅しているわけではありません。現在地は端末内でのみ利用し、サーバーには送信しません。地図データ © <a
+ href="https://www.openstreetmap.org/copyright"
+ target="_blank"
+ rel="noopener">OpenStreetMap</a
+ > contributors
+ </p>
+</details>
+
+<style>
+ .park-map-legend {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 0.4rem 1rem;
+ align-items: center;
+ margin-top: 0.5rem;
+ color: var(--sl-color-gray-2);
+ font-size: 0.8rem;
+ }
+ .park-map-legend span {
+ display: inline-flex;
+ align-items: center;
+ gap: 0.35rem;
+ }
+ .swatch {
+ display: inline-block;
+ width: 12px;
+ height: 12px;
+ border-radius: 2px;
+ }
+ .swatch-matched {
+ background: #e53935;
+ }
+ .swatch-unmatched {
+ background: #ffcdd2;
+ }
+ .swatch-nearby {
+ background: #42a5f5;
+ }
+ .swatch-facility {
+ background: #8e24aa;
+ border-radius: 50%;
+ }
+ .swatch-facility-nearby {
+ background: #fb8c00;
+ border-radius: 50%;
+ }
+ .swatch-boundary {
+ height: 0;
+ border-top: 4px solid #6a1b9a;
+ border-radius: 0;
+ background: transparent;
+ }
+ .swatch-fac {
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ width: 18px;
+ height: 18px;
+ margin-right: 0.3rem;
+ color: #fff;
+ font-style: normal;
+ font-size: 7px;
+ font-weight: 700;
+ line-height: 1;
+ }
+ .swatch-fac-toilet {
+ background: #455a64;
+ border-radius: 4px;
+ }
+ .swatch-fac-water {
+ background: #0277bd;
+ border-radius: 50%;
+ }
+ .park-map-note {
+ margin-top: 0.4rem;
+ color: var(--sl-color-gray-2);
+ font-size: 0.8rem;
+ }
+ .park-play-legend {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 0.35rem 0.8rem;
+ margin: 0.5rem 0 0;
+ color: var(--sl-color-gray-2);
+ font-size: 0.78rem;
+ }
+ .park-play-legend-item {
+ display: inline-flex;
+ align-items: center;
+ gap: 0.3rem;
+ }
+</style>
diff --git a/src/components/ParksFilters.astro b/src/components/ParksFilters.astro
new file mode 100644
index 0000000..bf65d6e
--- /dev/null
+++ b/src/components/ParksFilters.astro
@@ -0,0 +1,184 @@
+---
+// 公園・公共施設の一覧を絞り込むコントロール。地図の上に表示する。
+// 実際の絞り込みは ParksTable.astro のスクリプトが行う。
+import { parks, towns, total } from "@/data/parks-rows";
+import { PARK_ICONS } from "@/data/park-icons";
+
+const facilityTypes = [
+ "図書館",
+ "公民館",
+ "児童館",
+ "地域センター",
+ "市役所支所",
+ "文化施設",
+].filter((type) =>
+ parks.some((p) => p["施設"] === "1" && p["種別"] === type),
+);
+---
+
+<div class="parks-controls" data-parks-filters>
+ <label>
+ <span>種類</span>
+ <select data-parks-kind>
+ <option value="">すべて</option>
+ <option value="park">公園</option>
+ {facilityTypes.map((type) => (
+ <option value={type}>{type}</option>
+ ))}
+ </select>
+ </label>
+ <label>
+ <span>町名</span>
+ <select data-parks-town>
+ <option value="">すべての町名</option>
+ {towns.map((town) => (
+ <option value={town}>{town}</option>
+ ))}
+ </select>
+ </label>
+ <label>
+ <span>キーワード</span>
+ <input type="search" data-parks-search placeholder="名称・住所・設備など" />
+ </label>
+ <fieldset class="parks-facilities">
+ <legend>設備・遊具で絞る</legend>
+ <label><input type="checkbox" data-fac-filter value="toilet" />トイレ</label>
+ <label><input type="checkbox" data-fac-filter value="water" />水飲み場・給水</label>
+ <label>
+ <input type="checkbox" data-fac-filter value="picnic" />
+ <span class="filter-icon" set:html={PARK_ICONS.picnic.svg} />ピクニック・広場
+ </label>
+ <label><input type="checkbox" data-fac-filter value="toy" />遊具あり</label>
+ <label>
+ <input type="checkbox" data-fac-filter value="sand" />
+ <span class="filter-icon" set:html={PARK_ICONS.sand.svg} />砂場
+ </label>
+ <label>
+ <input type="checkbox" data-fac-filter value="swing" />
+ <span class="filter-icon" set:html={PARK_ICONS.swing.svg} />ブランコ
+ </label>
+ <label>
+ <input type="checkbox" data-fac-filter value="seesaw" />
+ <span class="filter-icon" set:html={PARK_ICONS.teeter.svg} />シーソー
+ </label>
+ <label>
+ <input type="checkbox" data-fac-filter value="spring" />
+ <span class="filter-icon" set:html={PARK_ICONS.spring.svg} />スプリング遊具
+ </label>
+ <label>
+ <input type="checkbox" data-fac-filter value="jungle" />
+ <span class="filter-icon" set:html={PARK_ICONS.climbing.svg} />ジャングルジム
+ </label>
+ <label>
+ <input type="checkbox" data-fac-filter value="plane" />
+ <span class="filter-icon" set:html={PARK_ICONS.airplane.svg} />ヒコーキ
+ </label>
+ <label>
+ <input type="checkbox" data-fac-filter value="slide" />
+ <span class="filter-icon" set:html={PARK_ICONS.slide.svg} />滑り台
+ </label>
+ <label>
+ <input type="checkbox" data-fac-filter value="complex" />
+ <span class="filter-icon" set:html={PARK_ICONS.playground.svg} />複合遊具
+ </label>
+ <label>
+ <input type="checkbox" data-fac-filter value="rope" />
+ <span class="filter-icon" set:html={PARK_ICONS.flyingfox.svg} />ロープウェイ
+ </label>
+ <label>
+ <input type="checkbox" data-fac-filter value="ball" />
+ <span class="filter-icon" set:html={PARK_ICONS.ball.svg} />ボール遊び
+ </label>
+ </fieldset>
+ <span class="parks-count" data-parks-count aria-live="polite">{total}件</span>
+</div>
+
+<p class="parks-disclaimer">
+ 情報には誤りが含まれる場合があります。最新の情報は各施設の公式ページでご確認ください。
+</p>
+
+<style>
+ .parks-controls {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 0.5rem 0.9rem;
+ align-items: center;
+ margin: 0 0 0.55rem;
+ }
+ .parks-controls label {
+ display: inline-flex;
+ align-items: center;
+ gap: 0.4rem;
+ min-height: 2.1rem;
+ font-size: 0.9rem;
+ line-height: 1.2;
+ }
+ .parks-controls label > span {
+ line-height: 1.2;
+ }
+ .parks-controls select,
+ .parks-controls input[type="search"] {
+ height: 2.1rem;
+ box-sizing: border-box;
+ padding: 0.25rem 0.5rem;
+ border: 1px solid var(--sl-color-hairline, #ccc);
+ border-radius: 0.3rem;
+ background: var(--sl-color-bg, #fff);
+ color: var(--sl-color-text, inherit);
+ font: inherit;
+ line-height: 1.2;
+ }
+ .parks-facilities {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 0.1rem 0.6rem;
+ align-items: center;
+ margin: 0;
+ padding: 0.2rem 0.5rem;
+ border: 1px solid var(--sl-color-hairline, #ccc);
+ border-radius: 0.3rem;
+ }
+ .parks-facilities legend {
+ padding: 0 0.2rem;
+ font-size: 0.78em;
+ color: inherit;
+ opacity: 0.7;
+ }
+ .parks-facilities label {
+ display: inline-flex;
+ align-items: center;
+ gap: 0.2rem;
+ min-height: 1.5rem;
+ font-size: 0.8rem;
+ line-height: 1.2;
+ }
+ .parks-facilities input[type="checkbox"] {
+ width: 0.9em;
+ height: 0.9em;
+ margin: 0;
+ }
+ .filter-icon {
+ display: inline-flex;
+ width: 18px;
+ height: 18px;
+ flex: none;
+ }
+ .filter-icon :global(svg) {
+ display: block;
+ width: 100%;
+ height: 100%;
+ }
+ :global(.filter-icon svg *) {
+ vector-effect: non-scaling-stroke;
+ }
+ .parks-count {
+ margin-left: auto;
+ font-size: 0.9rem;
+ opacity: 0.75;
+ }
+ .parks-disclaimer {
+ margin: 0 0 0.55rem;
+ color: var(--sl-color-gray-2);
+ font-size: 0.78rem;
+ }
+</style>
diff --git a/src/components/ParksTable.astro b/src/components/ParksTable.astro
index bea8ff2..65b8412 100644
--- a/src/components/ParksTable.astro
+++ b/src/components/ParksTable.astro
@@ -1,78 +1,9 @@
---
-// 小平市の公園一覧(/kodaira-data/parks/)を表示する。
-// データは src/data/kodaira-parks.json(市立332件+市立以外)。
+// 小平市の公園・周辺の公園・公共施設の一覧(/kodaira-data/parks/)を表示する。
+// データは src/data/parks-rows.ts で組み立てる。
// DOM を抑えるため、設備は1セルにまとめ、アイコンは CSS の擬似要素で描く。
// 絞り込み・並べ替え・カード表示は利用者の端末で実行する。
-import parksData from "@/data/kodaira-parks.json";
-import osmData from "@/data/parks-geojson";
-import nearbyData from "@/data/kodaira-nearby-parks.json";
-
-type Park = Record<string, string>;
-
-function nearbyCentroid(feature: any): [number, number] {
- const g = feature.geometry;
- const ring = g.type === "Polygon" ? g.coordinates[0] : g.coordinates[0][0];
- if (!ring?.length) return [0, 0];
- let lat = 0;
- let lon = 0;
- for (const [x, y] of ring) {
- lon += x;
- lat += y;
- }
- return [lat / ring.length, lon / ring.length];
-}
-
-// 市境500m以内の市外公園。小平市の公園と同じ表に「市外」バッジ付きで並べる。
-const nearbyRows: Park[] = ((nearbyData as any).features ?? []).map((f: any) => {
- const p = f.properties || {};
- const [lat, lon] = nearbyCentroid(f);
- const area = Math.round(Number(p.area_m2) || 0);
- const name = String(p.name || "").trim();
- // 市外の公園も公園名で開く。市名が分かる場合は市名を付ける。
- const mapsQuery = name
- ? p.city
- ? `${p.city}${name}`
- : name
- : `${lat},${lon}`;
- return {
- "公園名": name,
- "住所": p.city ? `${p.city}(市外)` : "市外",
- "町名": "市外",
- "面積㎡": area ? String(area) : "",
- "500㎡以上": "",
- "種別": "市外",
- "南西部指定管理": "",
- "トイレ": "",
- "水飲み場": "",
- "ベンチ・椅子": "",
- "テーブル": "",
- "パーゴラ": "",
- "東屋": "",
- "防災用具": "",
- "ボール遊び": "",
- "遊具": "",
- "駐車場": "",
- "その他設備": "",
- "緯度": String(lat),
- "経度": String(lon),
- "備考": `市外・小平市境から約${Math.round(Number(p.distance_m) || 0)}m`,
- "設置者": "市外",
- "状態": "",
- "地図キー": `${p.osm_type || ""}/${p.osm_id || ""}`,
- "地図URL": `https://www.google.com/maps/search/?api=1&query=${encodeURIComponent(mapsQuery)}`,
- };
-});
-
-const parks = [...(parksData as Park[]), ...nearbyRows];
-
-// OpenStreetMapにポリゴンがあり、地図から位置を表示できる公園名。
-// 市外の近隣公園も地図に表示しているので、同じように地図で見られる。
-const mappedNames = new Set<string>([
- ...(osmData as any).features.map((f: any) => f.properties?.our_name).filter(Boolean),
- ...((nearbyData as any).features ?? [])
- .map((f: any) => String(f.properties?.name || "").trim())
- .filter(Boolean),
-]);
+import { parks, mappedNames, type Park } from "@/data/parks-rows";
const EMPTY = "—";
@@ -87,6 +18,12 @@ const TYPE_LABEL: Record<string, string> = {
団地内公園: "団地内公園",
児童遊園: "児童遊園",
市外: "市外の近隣公園",
+ 地域センター: "地域センター",
+ 公民館: "公民館",
+ 児童館: "児童館",
+ 図書館: "図書館",
+ 市役所支所: "市役所支所",
+ 文化施設: "文化施設",
};
const TYPE_CLASS: Record<string, string> = {
街区: "parks-type--block",
@@ -98,6 +35,30 @@ const TYPE_CLASS: Record<string, string> = {
団地内公園: "parks-type--danchi",
児童遊園: "parks-type--jidou",
市外: "parks-type--green",
+ 地域センター: "parks-type--facility",
+ 公民館: "parks-type--facility",
+ 児童館: "parks-type--facility",
+ 図書館: "parks-type--facility",
+ 市役所支所: "parks-type--facility",
+ 文化施設: "parks-type--facility",
+};
+// 種別は列幅を小さくするため、漢字1文字の記号で表示する。
+const TYPE_MARK: Record<string, string> = {
+ 街区: "街",
+ 近隣: "近",
+ 運動: "運",
+ 広域: "広",
+ 広場: "場",
+ 緑地: "緑",
+ 団地内公園: "団",
+ 児童遊園: "児",
+ 市外: "外",
+ 地域センター: "📍",
+ 公民館: "🏛",
+ 児童館: "🧒",
+ 図書館: "📚",
+ 市役所支所: "🏢",
+ 文化施設: "🎭",
};
// 市立以外の公園に付けるバッジ(設置者が空欄なら市立として扱う)。
@@ -125,6 +86,9 @@ function facilityBadges(p: Park): Badge[] {
if (p["水飲み場"]) {
badges.push({ kind: "water", label: "水飲み場", title: `水飲み場: ${p["水飲み場"]}` });
}
+ if (p["給水"]) {
+ badges.push({ kind: "water", label: "給水", title: `給水: ${p["給水"]}` });
+ }
if (p["遊具"]) {
badges.push({ kind: "toy", label: "遊具", title: `遊具: ${p["遊具"]}` });
}
@@ -150,12 +114,34 @@ function facTokens(p: Park): string {
const tokens: string[] = [];
if (p["トイレ"]) tokens.push("toilet");
if (p["水飲み場"]) tokens.push("water");
+ if (p["給水"]) tokens.push("water");
if (p["遊具"]) tokens.push("toy");
+ const play = p["遊具"] || "";
+ if (play.includes("砂場")) tokens.push("sand");
+ if (play.includes("ブランコ")) tokens.push("swing");
+ if (play.includes("シーソー")) tokens.push("seesaw");
+ if (play.includes("スプリング")) tokens.push("spring");
+ if (play.includes("ジャングル")) tokens.push("jungle");
+ if (play.includes("ヒコーキ") || play.includes("飛行機")) tokens.push("plane");
+ if (play.includes("滑り台") || play.includes("滑台")) tokens.push("slide");
+ if (play.includes("複合遊具")) tokens.push("complex");
+ if (play.includes("ロープウェイ")) tokens.push("rope");
if (p["パーゴラ"]) tokens.push("pergola");
if (p["東屋"]) tokens.push("azumaya");
const ball = p["ボール遊び"];
if (ball && ball !== "禁止") tokens.push("ball");
if (p["南西部指定管理"]) tokens.push("cm");
+ // ピクニック広場・芝生広場・テーブルのある公園。
+ const picnicText = `${p["公園名"] || ""} ${p["種別"] || ""} ${p["その他設備"] || ""} ${p["備考"] || ""}`;
+ if (
+ (p["テーブル"] || "").trim() ||
+ p["種別"] === "広場" ||
+ picnicText.includes("芝生") ||
+ picnicText.includes("ピクニック") ||
+ picnicText.includes("広場")
+ ) {
+ tokens.push("picnic");
+ }
return tokens.join(" ");
}
@@ -228,56 +214,32 @@ function searchIndex(p: Park): string {
p["状態"],
p["トイレ"],
p["水飲み場"],
+ p["給水"],
p["ボール遊び"],
...DETAIL_FIELDS.map((f) => p[f.key]),
]
.join(" ")
.toLowerCase();
}
-
-const towns = [...new Set(parks.map((p) => p["町名"]).filter(Boolean))].sort((a, b) =>
- a.localeCompare(b, "ja"),
-);
-const total = parks.length;
---
<div class="parks" data-parks>
- <div class="parks-controls">
- <label>
- <span>町名</span>
- <select data-parks-town>
- <option value="">すべての町名</option>
- {towns.map((town) => (
- <option value={town}>{town}</option>
- ))}
- </select>
- </label>
- <label>
- <span>キーワード</span>
- <input type="search" data-parks-search placeholder="公園名・住所・遊具など" />
- </label>
- <fieldset class="parks-facilities">
- <legend>設備・管理で絞る</legend>
- <label><input type="checkbox" data-fac-filter value="toilet" />トイレ</label>
- <label><input type="checkbox" data-fac-filter value="water" />水飲み場</label>
- <label><input type="checkbox" data-fac-filter value="toy" />遊具</label>
- <label><input type="checkbox" data-fac-filter value="pergola" />パーゴラ</label>
- <label><input type="checkbox" data-fac-filter value="azumaya" />東屋</label>
- <label><input type="checkbox" data-fac-filter value="ball" />ボール遊び</label>
- <label><input type="checkbox" data-fac-filter value="cm" />指定管理</label>
- </fieldset>
- <span class="parks-count" data-parks-count aria-live="polite">{total}件</span>
- </div>
- <p class="parks-hint">設備の情報は、市の資料などに基づきます。設備で絞ると、この情報がある公園だけが対象になります。</p>
- <p class="parks-none" data-parks-none hidden>条件に合う公園が見つかりませんでした。</p>
+ <p class="parks-none" data-parks-none hidden>条件に合う公園・施設が見つかりませんでした。</p>
<div class="parks-scroll">
<table>
+ <colgroup>
+ <col class="col-name" />
+ <col class="col-address" />
+ <col class="col-area" />
+ <col class="col-type" />
+ <col class="col-facility" />
+ </colgroup>
<thead>
<tr>
<th scope="col" aria-sort="none">
<button type="button" class="parks-sort" data-sort="name">
- 公園名<span class="parks-sort-mark" aria-hidden="true"></span>
+ 名称<span class="parks-sort-mark" aria-hidden="true"></span>
</button>
</th>
<th scope="col">住所</th>
@@ -293,13 +255,14 @@ const total = parks.length;
<tbody>
{parks.map((park) => (
<tr
+ data-kind={park["施設"] === "1" ? park["種別"] : "park"}
data-town={park["町名"]}
data-area={park["面積㎡"]}
data-name={park["公園名"]}
data-fac={facTokens(park)}
data-search={searchIndex(park)}
>
- <td class="is-name" data-label="公園名">
+ <td class="is-name" data-label="名称">
{mappedNames.has(park["公園名"]) ? (
<button
type="button"
@@ -308,6 +271,14 @@ const total = parks.length;
data-focus-key={park["地図キー"] || ""}
title="地図でこの公園の位置を表示"
>{park["公園名"]}</button>
+ ) : park["公式URL"] ? (
+ <a
+ class="park-name-link"
+ href={park["公式URL"]}
+ target="_blank"
+ rel="noopener"
+ title="公式ページを開く"
+ >{park["公園名"]}</a>
) : (
park["公園名"]
)}
@@ -344,7 +315,7 @@ const total = parks.length;
title={TYPE_LABEL[park["種別"]]}
aria-label={TYPE_LABEL[park["種別"]]}
>
- {park["種別"]}
+ <span aria-hidden="true">{TYPE_MARK[park["種別"]] || park["種別"].slice(0, 1)}</span>
</span>
) : (
EMPTY
@@ -424,16 +395,35 @@ const total = parks.length;
opacity: 1;
}
.parks-scroll {
- overflow-x: auto;
+ max-height: 70vh;
+ overflow: auto;
+ overscroll-behavior: contain;
-webkit-overflow-scrolling: touch;
border: 1px solid var(--sl-color-hairline, #ddd);
border-radius: 0.3rem;
}
.parks table {
width: 100%;
+ min-width: 760px;
+ table-layout: fixed;
border-collapse: collapse;
font-size: 0.85rem;
}
+ .parks col.col-name {
+ width: 24%;
+ }
+ .parks col.col-address {
+ width: 18%;
+ }
+ .parks col.col-area {
+ width: 11%;
+ }
+ .parks col.col-type {
+ width: 7%;
+ }
+ .parks col.col-facility {
+ width: 40%;
+ }
.parks th,
.parks td {
border-bottom: 1px solid var(--sl-color-hairline, #ddd);
@@ -481,6 +471,9 @@ const total = parks.length;
}
.parks .is-name {
font-weight: 600;
+ white-space: normal;
+ overflow-wrap: anywhere;
+ line-height: 1.5;
}
.parks-owner {
display: inline-block;
@@ -521,6 +514,8 @@ const total = parks.length;
white-space: nowrap;
}
.park-name-link {
+ display: inline-block;
+ max-width: 100%;
padding: 0;
border: 0;
background: none;
@@ -532,6 +527,8 @@ const total = parks.length;
text-decoration: underline;
text-decoration-color: var(--sl-color-gray-4);
text-underline-offset: 2px;
+ white-space: normal;
+ overflow-wrap: anywhere;
}
.park-name-link:hover {
color: var(--sl-color-accent);
@@ -579,16 +576,15 @@ const total = parks.length;
.parks-type {
display: inline-flex;
align-items: center;
- gap: 0.3em;
- font-size: 0.9em;
- }
- .parks-type::before {
- content: "";
- width: 0.7em;
- height: 0.7em;
- border-radius: 50%;
- background: var(--type-color, #888);
- flex: none;
+ justify-content: center;
+ width: 1.5em;
+ height: 1.5em;
+ border-radius: 0.35em;
+ background: color-mix(in srgb, var(--type-color, #888) 18%, transparent);
+ color: var(--type-color, #888);
+ font-size: 0.8em;
+ font-weight: 700;
+ line-height: 1;
}
.parks-type--block {
--type-color: #2e9e4f;
@@ -614,6 +610,10 @@ const total = parks.length;
.parks-type--jidou {
--type-color: #d81b60;
}
+ .parks-type--facility {
+ --type-color: #00838f;
+ font-size: 1em;
+ }
.parks .is-facility {
white-space: normal;
min-width: 12rem;
@@ -674,12 +674,15 @@ const total = parks.length;
<script>
document.querySelectorAll("[data-parks]").forEach((root) => {
- const select = root.querySelector<HTMLSelectElement>("[data-parks-town]");
- const search = root.querySelector<HTMLInputElement>("[data-parks-search]");
- const count = root.querySelector("[data-parks-count]");
+ const select = document.querySelector<HTMLSelectElement>("[data-parks-town]");
+ const kindSelect = document.querySelector<HTMLSelectElement>("[data-parks-kind]");
+ const search = document.querySelector<HTMLInputElement>("[data-parks-search]");
+ const count = document.querySelector("[data-parks-count]");
const none = root.querySelector<HTMLElement>("[data-parks-none]");
const tbody = root.querySelector("tbody");
- const checks = Array.from(root.querySelectorAll<HTMLInputElement>("[data-fac-filter]"));
+ const checks = Array.from(
+ document.querySelectorAll<HTMLInputElement>("[data-fac-filter]"),
+ );
const sortButtons = Array.from(root.querySelectorAll<HTMLButtonElement>("[data-sort]"));
if (!tbody) return;
@@ -703,17 +706,19 @@ const total = parks.length;
let selectedName = "";
const applyFilter = () => {
+ const kind = kindSelect ? kindSelect.value : "";
const town = select ? select.value : "";
const query = search ? search.value.trim().toLowerCase() : "";
const wanted = checks.filter((c) => c.checked).map((c) => c.value);
let shown = 0;
allRows().forEach((row) => {
const facs = (row.dataset.fac || "").split(" ");
+ const okKind = !kind || row.dataset.kind === kind;
const okTown = !town || row.dataset.town === town;
const okText = !query || (row.dataset.search || "").includes(query);
const okFac = wanted.every((token) => facs.includes(token));
const okSelected = !selectedName || row.dataset.name === selectedName;
- const ok = okTown && okText && okFac && okSelected;
+ const ok = okKind && okTown && okText && okFac && okSelected;
row.classList.toggle("is-hidden", !ok);
if (ok) shown += 1;
});
@@ -729,7 +734,7 @@ const total = parks.length;
new CustomEvent("park:filter", {
detail: {
names: visibleNames,
- active: Boolean(town || query || wanted.length || selectedName),
+ active: Boolean(kind || town || query || wanted.length || selectedName),
fromMap,
},
}),
@@ -765,6 +770,10 @@ const total = parks.length;
clearSelected();
applyFilter();
});
+ kindSelect?.addEventListener("change", () => {
+ clearSelected();
+ applyFilter();
+ });
search?.addEventListener("input", () => {
clearSelected();
applyFilter();
@@ -784,6 +793,7 @@ const total = parks.length;
selectedName = name;
if (search) search.value = name;
if (select) select.value = "";
+ if (kindSelect) kindSelect.value = "";
checks.forEach((c) => {
c.checked = false;
});
diff --git a/src/content/docs/kodaira-data/parks.mdx b/src/content/docs/kodaira-data/parks.mdx
index b1480d4..429e21a 100644
--- a/src/content/docs/kodaira-data/parks.mdx
+++ b/src/content/docs/kodaira-data/parks.mdx
@@ -1,32 +1,33 @@
---
-title: 小平市の公園一覧
-description: 小平市内の公園355件と市境500m以内の市外公園46件を、町名・キーワード・設備で検索できる一覧にまとめました。都立公園や都営・UR住宅内の公園、所有者未確認の緑地も含みます。小平市議会議員 安竹洋平の活動記録です。問題の経緯、市の対応、議会での質疑や答弁、関連する資料や会議録へのリンクをまとめています。市政の課題解決に向けた取り組みの記録としてご覧ください。
+title: こだいら 公園さんぽマップ
+draft: true
+description: 小平市と周辺の公園・公共施設一覧(愛称:こだいら 公園さんぽマップ)。小平市内の公園355件と市境500m以内の市外公園48件、周辺の図書館・公民館・児童館などの公共施設を、町名・キーワード・設備で検索できる一覧にまとめました。都立公園や都営・UR住宅内の公園、所有者未確認の緑地も含みます。小平市議会議員 安竹洋平の活動記録です。
---
+import ParksFilters from '@/components/ParksFilters.astro';
import ParksTable from '@/components/ParksTable.astro';
import ParkMap from '@/components/ParkMap.astro';
-import FacilitiesTable from '@/components/FacilitiesTable.astro';
+import ParkMapHelp from '@/components/ParkMapHelp.astro';
import PwaRegister from '@/components/PwaRegister.astro';
-小平市内の公園と、市外にまたがる都立小金井公園、所有者未確認の緑地などの一覧です。市境500m以内の市外公園も同じ表に「市外」バッジ付きで含めています。町名や設備で絞り込んだり、公園名や住所、遊具などのキーワードで検索したりできます。公園名と面積の見出しを押すと、並べ替えられます。住所を押すと、公園名でGoogleマップを開きます。公園名の横の「都立」「都営」「UR」「民間」「未確認」などのバッジは、市立以外または所有者・名称が未確認の公園・緑地であることを示します。スマートフォンでは表を横にスクロールしてご覧ください。
+<ParksFilters />
-:::note
-設備(トイレ・水飲み場・遊具など)の情報は、すべての公園についてそろっているわけではありません。情報が不足している公園については、今後、順次追記していく予定です。
-:::
+<ParkMap />
-:::note
-対応ブラウザでは、アドレスバーのインストールアイコンから、このページをアプリとして保存できます。ホーム画面に追加すると、地図・一覧をアプリのように開けます。オフライン時は、一度開いたページと表を表示できます(地図タイルは通信が必要です)。
-:::
+<ParksTable />
-<PwaRegister />
+<ParkMapHelp />
-## 公園の位置
+<details class="page-help">
+<summary>設備情報について</summary>
-<ParkMap />
+設備(トイレ・水飲み場・給水・遊具など)の情報は、すべての公園・施設についてそろっているわけではありません。情報が不足している公園については、今後、順次追記していく予定です。上のフィルタは、公園と公共施設の両方に適用されます。「設備・遊具で絞る」では砂場・ブランコ・シーソー・スプリング遊具・ジャングルジム・ヒコーキ・滑り台・複合遊具・ロープウェイで絞れます。「ピクニック・広場」は、広場・テーブル・芝生のある公園をまとめて表示します。
-<ParksTable />
+</details>
+
+<details class="page-help">
+<summary>種別の見方</summary>
-:::note
「種別」の「街区」「近隣」「運動」「広域」は、都市公園法に基づく公園の区分です。「広場」「緑地」「団地内公園」「児童遊園」は、この一覧独自の分類です。
- **街区公園**:主に近くに住む人が利用する公園。おおむね2,500㎡が標準。
@@ -37,40 +38,65 @@ import PwaRegister from '@/components/PwaRegister.astro';
- **緑地**:公園台帳に載っていない緑地・樹林地など。
- **団地内公園**:都営住宅などの団地内にある公園。
- **児童遊園**:地域の児童遊園。
-:::
-:::note
-「市外」バッジの公園は、小平市の市境から500m以内にある市外の公園です。小平市の公園一覧(355件)とは別に、同じ表に含めています。距離は市境までの目安です。Googleマップのリンクは公園名で開きます。
-:::
+表の「種別」は列幅を小さくするため、漢字1文字の記号で表示しています。街=街区公園、近=近隣公園、運=運動公園、広=広域公園、場=広場、緑=緑地、団=団地内公園、児=児童遊園、外=市外の近隣公園です。公共施設は、📍=地域センター、🏛=公民館、🧒=児童館、📚=図書館、🏢=市役所支所、🎭=文化施設です。記号にカーソルを合わせると正式名が表示されます。
-:::note
-**手入力ポリゴンのライセンス**: このページの手入力ポリゴン(公園の範囲)は安竹洋平が作成したものです。正確な境界座標ではありません。出典として「安竹洋平(https://yasutakeyohei.com/)」を明示すれば、自由に利用できます。ライセンスは [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/deed.ja) です([ライセンス全文](/kodaira-data/parks/LICENSE.txt))。OSM由来のデータはODbLです。
-:::
+</details>
-## 暑さ・寒さをしのげる公共施設
+<details class="page-help">
+<summary>市外の近隣公園について</summary>
-地域センター・公民館・図書館・市役所支所・文化施設の一覧です。トイレ・給水・開館時間を確認できます。暑さ・寒さをしのぐ場所を探すときの参考にしてください。
+「市外」バッジの公園は、小平市の市境から500m以内にある市外の公園です。小平市の公園一覧(355件)とは別に、同じ表に含めています。距離は市境までの目安です。Googleマップのリンクは公園名で開きます。範囲が取得できない公園は、地図では丸(点)で表示しています。
-<FacilitiesTable />
+</details>
-## この一覧について
+<details class="page-help">
+<summary>公共施設について</summary>
+
+小平市内の地域センター・公民館・図書館・市役所支所・文化施設と、市境500m以内の市外の図書館・公民館・児童館を、公園と同じ表に含めています。公共施設の行は、種別・開館時間・休館日・トイレ・給水を「施設・備考」にまとめています。市外施設の情報はOpenStreetMapによるもので、トイレ・給水は「未確認」としています。
+
+</details>
+
+<details class="page-help">
+<summary>この一覧について</summary>
+
+「こだいら 公園さんぽマップ」は、小平市と周辺の公園・公共施設の一覧です。
-:::note
- 面積の「小・中・大」は目安です。小は1000㎡未満、中は1000〜10000㎡、大は10000㎡以上としています。
- 「種別」は一部の公園のみ掲載しています。全市分は公開されていません。
-- 公園名の横に「都立」「都営」「UR」「民間」「未確認」などのバッジがある公園は、市立以外または所有者・名称が未確認の公園・緑地です。
+- 名称の横に「都立」「都営」「UR」「民間」「未確認」などのバッジがある公園は、市立以外または所有者・名称が未確認の公園・緑地です。
- 「都立」は都立公園、「都営」は東京都営住宅内の公園・児童遊園、「UR」はUR都市機構の団地内の公園です。
-- 「市外」バッジの公園は市外の近隣公園です。小平市の公園一覧(355件)には含めていませんが、表には表示しています。
+- 「市外」バッジの公園・施設は、小平市の市境から500m以内にある市外の公園・公共施設です。小平市の公園一覧(355件)には含めていませんが、表には表示しています。
- 「閉鎖」バッジの公園は現在閉鎖中です。
- 名前のない緑地は「緑地(OSM 番号)」と表示しています。番号はOpenStreetMapのIDです。
-- 設備の情報は、すべての公園についてそろっているわけではありません。設備で絞ると、この情報がある公園だけが対象になります。
+- 公共施設の行は、種別・開館時間・休館日・トイレ・給水を「施設・備考」にまとめています。市外の公共施設はOpenStreetMapをもとにしています。
+- 設備の情報は、すべての公園・施設についてそろっているわけではありません。設備で絞ると、この情報がある公園・施設だけが対象になります。
- 設備の情報は、現在と異なる場合や、記載の誤りが含まれる場合があります。ご了承ください。
- 面積が不明な11公園も掲載しています。面積は「—」としています。
- 空欄は「—」で示しています。情報の記載がないという意味であり、設備がないという意味ではありません。
-:::
-## ほかのサイトでの公園紹介
+</details>
+
+<details class="page-help">
+<summary>アプリとして保存</summary>
+
+対応ブラウザでは、アドレスバーのインストールアイコンから、このページをアプリとして保存できます。ホーム画面に追加すると、地図・一覧をアプリのように開けます。オフライン時は、一度開いたページと表を表示できます(地図タイルは通信が必要です)。
+
+</details>
+
+<PwaRegister />
+
+<details class="page-help">
+<summary>ほかのサイトでの公園紹介</summary>
PARKFULというサイトでも、小平市の公園の紹介が掲載されています。
- [PARKFUL(外部サイト)](https://parkful.net/)
+
+</details>
+
+## ライセンス
+
+:::note
+**手入力ポリゴンのライセンス**: このページの手入力ポリゴン(公園の範囲)は安竹洋平が作成したものです。正確な境界座標ではありません。出典として「安竹洋平(https://yasutakeyohei.com/)」を明示すれば、自由に利用できます。ライセンスは [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/deed.ja) です([ライセンス全文](/kodaira-data/parks/LICENSE.txt))。OSM由来のデータはODbLです。地図の遊具アイコン(ブランコ、シーソー、スプリング遊具、砂場、複合遊具、ピクニック・広場、ジャングルジム、ヒコーキ、滑り台、ロープウェイ、ボール遊び)は [SVGRepo](https://www.svgrepo.com/) の素材を利用しています。各素材の作者・ライセンスは SVGRepo の該当ページおよび[ライセンス説明](https://www.svgrepo.com/page/licensing/)をご確認ください。
+:::
diff --git a/src/data/kodaira-nearby-facilities.json b/src/data/kodaira-nearby-facilities.json
new file mode 100644
index 0000000..bb0cb99
--- /dev/null
+++ b/src/data/kodaira-nearby-facilities.json
@@ -0,0 +1,306 @@
+[
+ {
+ "name": "若葉児童館",
+ "type": "児童館",
+ "address": "",
+ "hours": "",
+ "closed": "",
+ "toilet": "未確認",
+ "water": "未確認",
+ "note": "市外・小平市境から約56m(OpenStreetMap)",
+ "source": "https://www.openstreetmap.org/node/1420796574",
+ "lat": 35.723946,
+ "lon": 139.437154,
+ "geocode": "OSM",
+ "city": "",
+ "distance_m": 56,
+ "osm_type": "node",
+ "osm_id": 1420796574,
+ "nearby": true
+ },
+ {
+ "name": "西集会場",
+ "type": "公民館",
+ "address": "",
+ "hours": "",
+ "closed": "",
+ "toilet": "未確認",
+ "water": "未確認",
+ "note": "市外・小平市境から約62m(OpenStreetMap)",
+ "source": "https://www.openstreetmap.org/node/2137169484",
+ "lat": 35.723583,
+ "lon": 139.438922,
+ "geocode": "OSM",
+ "city": "",
+ "distance_m": 62,
+ "osm_type": "node",
+ "osm_id": 2137169484,
+ "nearby": true
+ },
+ {
+ "name": "東久留米市立滝山図書館",
+ "type": "図書館",
+ "address": "東久留米市滝山四丁目1-10",
+ "hours": "",
+ "closed": "",
+ "toilet": "未確認",
+ "water": "未確認",
+ "note": "市外・小平市境から約198m(OpenStreetMap)",
+ "source": "https://www.openstreetmap.org/node/1420782537",
+ "lat": 35.7448193,
+ "lon": 139.5044328,
+ "geocode": "OSM",
+ "city": "東久留米市",
+ "distance_m": 198,
+ "osm_type": "node",
+ "osm_id": 1420782537,
+ "nearby": true
+ },
+ {
+ "name": "東村山市立萩山図書館",
+ "type": "図書館",
+ "address": "東村山市萩山町二丁目13-1",
+ "hours": "",
+ "closed": "",
+ "toilet": "未確認",
+ "water": "未確認",
+ "note": "市外・小平市境から約203m(OpenStreetMap)",
+ "source": "https://www.openstreetmap.org/node/1420785828",
+ "lat": 35.741577,
+ "lon": 139.478659,
+ "geocode": "OSM",
+ "city": "東村山市",
+ "distance_m": 203,
+ "osm_type": "node",
+ "osm_id": 1420785828,
+ "nearby": true
+ },
+ {
+ "name": "滝山児童館",
+ "type": "児童館",
+ "address": "",
+ "hours": "",
+ "closed": "",
+ "toilet": "未確認",
+ "water": "未確認",
+ "note": "市外・小平市境から約209m(OpenStreetMap)",
+ "source": "https://www.openstreetmap.org/node/1420789295",
+ "lat": 35.7448811,
+ "lon": 139.504537,
+ "geocode": "OSM",
+ "city": "",
+ "distance_m": 209,
+ "osm_type": "node",
+ "osm_id": 1420789295,
+ "nearby": true
+ },
+ {
+ "name": "東村山市立富士見図書館",
+ "type": "図書館",
+ "address": "東京都東村山市富士見町1-7-35",
+ "hours": "",
+ "closed": "",
+ "toilet": "未確認",
+ "water": "未確認",
+ "note": "市外・小平市境から約236m(OpenStreetMap)",
+ "source": "https://www.openstreetmap.org/node/1420785824",
+ "lat": 35.744013,
+ "lon": 139.461267,
+ "geocode": "OSM",
+ "city": "",
+ "distance_m": 236,
+ "osm_type": "node",
+ "osm_id": 1420785824,
+ "nearby": true
+ },
+ {
+ "name": "西東京市芝久保児童館",
+ "type": "児童館",
+ "address": "",
+ "hours": "",
+ "closed": "",
+ "toilet": "未確認",
+ "water": "未確認",
+ "note": "市外・小平市境から約285m(OpenStreetMap)",
+ "source": "https://www.openstreetmap.org/node/12609116867",
+ "lat": 35.7247015,
+ "lon": 139.5257321,
+ "geocode": "OSM",
+ "city": "",
+ "distance_m": 285,
+ "osm_type": "node",
+ "osm_id": 12609116867,
+ "nearby": true
+ },
+ {
+ "name": "くぬぎ児童館",
+ "type": "児童館",
+ "address": "東久留米市前沢四丁目6-3",
+ "hours": "",
+ "closed": "",
+ "toilet": "未確認",
+ "water": "未確認",
+ "note": "市外・小平市境から約304m(OpenStreetMap)",
+ "source": "https://www.openstreetmap.org/node/1420763963",
+ "lat": 35.744363,
+ "lon": 139.512841,
+ "geocode": "OSM",
+ "city": "東久留米市",
+ "distance_m": 304,
+ "osm_type": "node",
+ "osm_id": 1420763963,
+ "nearby": true
+ },
+ {
+ "name": "栄町児童館",
+ "type": "児童館",
+ "address": "東村山市栄町三丁目14-1",
+ "hours": "",
+ "closed": "",
+ "toilet": "未確認",
+ "water": "未確認",
+ "note": "市外・小平市境から約325m(OpenStreetMap)",
+ "source": "https://www.openstreetmap.org/node/1420786210",
+ "lat": 35.746611,
+ "lon": 139.469178,
+ "geocode": "OSM",
+ "city": "東村山市",
+ "distance_m": 325,
+ "osm_type": "node",
+ "osm_id": 1420786210,
+ "nearby": true
+ },
+ {
+ "name": "西東京市芝久保コミュニティセンター",
+ "type": "公民館",
+ "address": "",
+ "hours": "",
+ "closed": "",
+ "toilet": "未確認",
+ "water": "未確認",
+ "note": "市外・小平市境から約395m(OpenStreetMap)",
+ "source": "https://www.openstreetmap.org/node/12592346994",
+ "lat": 35.7291938,
+ "lon": 139.5218464,
+ "geocode": "OSM",
+ "city": "",
+ "distance_m": 395,
+ "osm_type": "node",
+ "osm_id": 12592346994,
+ "nearby": true
+ },
+ {
+ "name": "富士見児童館",
+ "type": "児童館",
+ "address": "東京都東村山市富士見町5-4-51",
+ "hours": "",
+ "closed": "",
+ "toilet": "未確認",
+ "water": "未確認",
+ "note": "市外・小平市境から約415m(OpenStreetMap)",
+ "source": "https://www.openstreetmap.org/node/1420775215",
+ "lat": 35.746689,
+ "lon": 139.462891,
+ "geocode": "OSM",
+ "city": "",
+ "distance_m": 415,
+ "osm_type": "node",
+ "osm_id": 1420775215,
+ "nearby": true
+ },
+ {
+ "name": "立川市若葉図書館",
+ "type": "図書館",
+ "address": "東京都立川市若葉町3-34-1",
+ "hours": "",
+ "closed": "",
+ "toilet": "未確認",
+ "water": "未確認",
+ "note": "市外・小平市境から約426m(OpenStreetMap)",
+ "source": "https://www.openstreetmap.org/node/1420795509",
+ "lat": 35.720189,
+ "lon": 139.439191,
+ "geocode": "OSM",
+ "city": "",
+ "distance_m": 426,
+ "osm_type": "node",
+ "osm_id": 1420795509,
+ "nearby": true
+ },
+ {
+ "name": "東大和市立さくらがおか児童館",
+ "type": "児童館",
+ "address": "東京都東大和市桜が丘3-44-13",
+ "hours": "",
+ "closed": "",
+ "toilet": "未確認",
+ "water": "未確認",
+ "note": "市外・小平市境から約440m(OpenStreetMap)",
+ "source": "https://www.openstreetmap.org/node/1420785706",
+ "lat": 35.733778,
+ "lon": 139.420016,
+ "geocode": "OSM",
+ "city": "",
+ "distance_m": 440,
+ "osm_type": "node",
+ "osm_id": 1420785706,
+ "nearby": true
+ },
+ {
+ "name": "東大和市立桜が丘図書館",
+ "type": "図書館",
+ "address": "東京都東大和市桜が丘3-44-13",
+ "hours": "",
+ "closed": "",
+ "toilet": "未確認",
+ "water": "未確認",
+ "note": "市外・小平市境から約440m(OpenStreetMap)",
+ "source": "https://www.openstreetmap.org/node/1420785723",
+ "lat": 35.733789,
+ "lon": 139.420043,
+ "geocode": "OSM",
+ "city": "",
+ "distance_m": 440,
+ "osm_type": "node",
+ "osm_id": 1420785723,
+ "nearby": true
+ },
+ {
+ "name": "国分寺市立本多図書館",
+ "type": "図書館",
+ "address": "国分寺市本多一丁目7-1",
+ "hours": "",
+ "closed": "",
+ "toilet": "未確認",
+ "water": "未確認",
+ "note": "市外・小平市境から約475m(OpenStreetMap)",
+ "source": "https://www.openstreetmap.org/node/1420771584",
+ "lat": 35.705356,
+ "lon": 139.482337,
+ "geocode": "OSM",
+ "city": "国分寺市",
+ "distance_m": 475,
+ "osm_type": "node",
+ "osm_id": 1420771584,
+ "nearby": true
+ },
+ {
+ "name": "本多児童館",
+ "type": "児童館",
+ "address": "国分寺市本多一丁目7-1",
+ "hours": "",
+ "closed": "",
+ "toilet": "未確認",
+ "water": "未確認",
+ "note": "市外・小平市境から約486m(OpenStreetMap)",
+ "source": "https://www.openstreetmap.org/node/1420781732",
+ "lat": 35.7052411,
+ "lon": 139.4823082,
+ "geocode": "OSM",
+ "city": "国分寺市",
+ "distance_m": 486,
+ "osm_type": "node",
+ "osm_id": 1420781732,
+ "nearby": true
+ }
+]
diff --git a/src/data/kodaira-nearby-parks.json b/src/data/kodaira-nearby-parks.json
index bf93411..81985d3 100644
--- a/src/data/kodaira-nearby-parks.json
+++ b/src/data/kodaira-nearby-parks.json
@@ -1 +1 @@
-{"type":"FeatureCollection","features":[{"type":"Feature","properties":{"name":"すみれ公園","distance_m":4,"area_m2":1118,"osm_type":"way","osm_id":542686107,"city":"","note":"市外・小平市境界から500m以内"},"geometry":{"type":"Polygon","coordinates":[[[139.49887,35.7458891],[139.4987681,35.745741],[139.4984301,35.7459239],[139.4986072,35.7462004],[139.4988244,35.7460828],[139.4987949,35.7459696],[139.49887,35.7458891]]]}},{"type":"Feature","properties":{"name":"若葉緑地","distance_m":4,"area_m2":3395,"osm_type":"way","osm_id":591305877,"city":"","note":"市外・小平市境界から500m以内"},"geometry":{"type":"Polygon","coordinates":[[[139.4348041,35.7255946],[139.4341234,35.7255259],[139.4341039,35.7250579],[139.4344686,35.7250685],[139.4344816,35.7252139],[139.4349962,35.725235],[139.4350255,35.7252958],[139.4348041,35.7255946]]]}},{"type":"Feature","properties":{"name":"あじさい公園","distance_m":5,"area_m2":2317,"osm_type":"way","osm_id":1521995587,"city":"","note":"市外・小平市境界から500m以内"},"geometry":{"type":"Polygon","coordinates":[[[139.5066696,35.7418588],[139.5062131,35.7420472],[139.5059587,35.7416542],[139.5064167,35.7414578],[139.5066696,35.7418588]]]}},{"type":"Feature","properties":{"name":"富士見町1丁目第2仲よし広場","distance_m":5,"area_m2":1727,"osm_type":"way","osm_id":965224418,"city":"","note":"市外・小平市境界から500m以内"},"geometry":{"type":"Polygon","coordinates":[[[139.4551618,35.7387211],[139.4563827,35.739249],[139.4557987,35.7392483],[139.4557816,35.7390298],[139.4551012,35.7389491],[139.4551099,35.7388152],[139.4551618,35.7387211]]]}},{"type":"Feature","properties":{"name":"青梅橋公園","distance_m":22,"area_m2":388,"osm_type":"way","osm_id":754232094,"city":"","note":"市外・小平市境界から500m以内"},"geometry":{"type":"Polygon","coordinates":[[[139.4324421,35.7321674],[139.4327844,35.7321617],[139.4328439,35.7321892],[139.4328557,35.7321666],[139.4324314,35.7319798],[139.4324421,35.7321674]]]}},{"type":"Feature","properties":{"name":"桜が丘一丁目公園","distance_m":28,"area_m2":3067,"osm_type":"way","osm_id":754232096,"city":"","note":"市外・小平市境界から500m以内"},"geometry":{"type":"Polygon","coordinates":[[[139.4306727,35.7316731],[139.4314557,35.7316397],[139.4323502,35.7321376],[139.4323444,35.732073],[139.4323392,35.7320163],[139.4323165,35.7319804],[139.430697,35.7312184],[139.4306426,35.7312446],[139.4306727,35.7316731]]]}},{"type":"Feature","properties":{"name":"青梅橋東公園","distance_m":28,"area_m2":148,"osm_type":"way","osm_id":754232095,"city":"","note":"市外・小平市境界から500m以内"},"geometry":{"type":"Polygon","coordinates":[[[139.4329793,35.7324124],[139.4332489,35.7324111],[139.4329747,35.7323036],[139.4329793,35.7324124]]]}},{"type":"Feature","properties":{"name":"南台公園","distance_m":34,"area_m2":7777,"osm_type":"way","osm_id":591322526,"city":"","note":"市外・小平市境界から500m以内"},"geometry":{"type":"Polygon","coordinates":[[[139.4586433,35.7420302],[139.4591958,35.7420476],[139.4592366,35.7420302],[139.4593017,35.7410812],[139.4591617,35.7410363],[139.4592431,35.7408433],[139.4588588,35.7406583],[139.4586439,35.740986],[139.4586433,35.7420302]]]}},{"type":"Feature","properties":{"name":"用水北緑地","distance_m":51,"area_m2":2199,"osm_type":"way","osm_id":693736574,"city":"","note":"市外・小平市境界から500m以内"},"geometry":{"type":"Polygon","coordinates":[[[139.4426016,35.7373346],[139.4426667,35.7367311],[139.4427431,35.736731],[139.4425606,35.7382661],[139.4427828,35.7382803],[139.4427783,35.7383217],[139.4425624,35.7383098],[139.4424377,35.7392776],[139.4424678,35.7393173],[139.4423803,35.7393139],[139.4424744,35.7384284],[139.4423704,35.7384089],[139.4422463,35.7384134],[139.4422664,35.7382484],[139.4425005,35.7382633],[139.4426016,35.7373346]]]}},{"type":"Feature","properties":{"name":"富士見町2丁目第2仲よし広場","distance_m":64,"area_m2":76,"osm_type":"way","osm_id":965225385,"city":"","note":"市外・小平市境界から500m以内"},"geometry":{"type":"Polygon","coordinates":[[[139.4548178,35.7393066],[139.454867,35.73931],[139.4549317,35.7392079],[139.4548302,35.7392088],[139.4548178,35.7393066]]]}},{"type":"Feature","properties":{"name":"萩山公園","distance_m":69,"area_m2":9856,"osm_type":"way","osm_id":1462182280,"city":"","note":"市外・小平市境界から500m以内"},"geometry":{"type":"Polygon","coordinates":[[[139.473544,35.743935],[139.4735794,35.7439436],[139.474243,35.7435759],[139.4737767,35.7426251],[139.4728893,35.743005],[139.4729362,35.7431142],[139.4730193,35.7432377],[139.473544,35.743935]]]}},{"type":"Feature","properties":{"name":"コウヤマキ公園","distance_m":76,"area_m2":234,"osm_type":"way","osm_id":817978652,"city":"","note":"市外・小平市境界から500m以内"},"geometry":{"type":"Polygon","coordinates":[[[139.4935696,35.7084541],[139.4935476,35.708332],[139.4937318,35.7083087],[139.4937538,35.708417],[139.4937284,35.7084376],[139.4935696,35.7084541]]]}},{"type":"Feature","properties":{"name":"萩山四季の森公園","distance_m":76,"area_m2":9260,"osm_type":"way","osm_id":375322224,"city":"","note":"市外・小平市境界から500m以内"},"geometry":{"type":"Polygon","coordinates":[[[139.4753838,35.7425524],[139.4754466,35.7428113],[139.4754044,35.7430008],[139.474911,35.7431718],[139.4742411,35.7435494],[139.4737718,35.7426025],[139.4742316,35.7424093],[139.4745409,35.7428655],[139.4753838,35.7425524]]]}},{"type":"Feature","properties":{"name":"北町公園","distance_m":77,"area_m2":4613,"osm_type":"way","osm_id":591177446,"city":"","note":"市外・小平市境界から500m以内"},"geometry":{"type":"Polygon","coordinates":[[[139.4510419,35.721191],[139.4516704,35.721111],[139.4514732,35.7203655],[139.4510357,35.7204256],[139.4510542,35.7205457],[139.4508817,35.7205657],[139.4510419,35.721191]]]}},{"type":"Feature","properties":{"name":"芝久保三丁目ふれあい公園","distance_m":88,"area_m2":2550,"osm_type":"way","osm_id":1362560908,"city":"","note":"市外・小平市境界から500m以内"},"geometry":{"type":"Polygon","coordinates":[[[139.5191406,35.7293977],[139.5191246,35.729057],[139.5189069,35.7290647],[139.5189106,35.7291702],[139.5187826,35.7291731],[139.5187789,35.7290676],[139.5183128,35.7290842],[139.5183419,35.7292174],[139.5183864,35.7294214],[139.5187654,35.7294077],[139.5187763,35.7294125],[139.518822,35.7294106],[139.5191406,35.7293977]]]}},{"type":"Feature","properties":{"name":"萩山公園","distance_m":105,"area_m2":2063,"osm_type":"way","osm_id":558149589,"city":"","note":"市外・小平市境界から500m以内"},"geometry":{"type":"Polygon","coordinates":[[[139.4753972,35.7422672],[139.4753234,35.7420898],[139.4752765,35.7419395],[139.4757566,35.7417251],[139.475935,35.74208],[139.4753972,35.7422672]]]}},{"type":"Feature","properties":{"name":"さつき公園","distance_m":113,"area_m2":1974,"osm_type":"way","osm_id":543026519,"city":"","note":"市外・小平市境界から500m以内"},"geometry":{"type":"Polygon","coordinates":[[[139.5096639,35.7411551],[139.5094266,35.7407812],[139.5098426,35.7406074],[139.5100752,35.74099],[139.5096639,35.7411551]]]}},{"type":"Feature","properties":{"name":"桜町こぶし公園","distance_m":121,"area_m2":152,"osm_type":"way","osm_id":593771700,"city":"","note":"市外・小平市境界から500m以内"},"geometry":{"type":"Polygon","coordinates":[[[139.5094476,35.7133134],[139.5096078,35.7133184],[139.5096113,35.7132257],[139.5094432,35.7132222],[139.5094476,35.7133134]]]}},{"type":"Feature","properties":{"name":"富士見町1丁目第3仲よし広場","distance_m":184,"area_m2":1041,"osm_type":"way","osm_id":668907354,"city":"東村山市","note":"市外・小平市境界から500m以内"},"geometry":{"type":"Polygon","coordinates":[[[139.4624137,35.7440997],[139.4619222,35.7440867],[139.4619188,35.7440971],[139.4619148,35.7442438],[139.4619138,35.7442969],[139.4624022,35.7443098],[139.4624137,35.7440997]]]}},{"type":"Feature","properties":{"name":"ひょうたん公園","distance_m":214,"area_m2":3515,"osm_type":"way","osm_id":563674138,"city":"","note":"市外・小平市境界から500m以内"},"geometry":{"type":"Polygon","coordinates":[[[139.4974454,35.7085293],[139.497419,35.708478],[139.4973493,35.7082461],[139.4973206,35.708145],[139.4973091,35.7081114],[139.4972735,35.7079576],[139.4972279,35.707808],[139.4975624,35.7077753],[139.4977517,35.7077645],[139.4978495,35.7085013],[139.4976645,35.7085113],[139.4974454,35.7085293]]]}},{"type":"Feature","properties":{"name":"東大和南公園","distance_m":218,"area_m2":100408,"osm_type":"way","osm_id":165197251,"city":"","note":"市外・小平市境界から500m以内"},"geometry":{"type":"Polygon","coordinates":[[[139.4209315,35.7317592],[139.4210368,35.7335495],[139.4228427,35.7334823],[139.4251194,35.7333976],[139.4252208,35.7346496],[139.4239703,35.7347091],[139.4222181,35.734803],[139.4222618,35.735362],[139.4224708,35.7353468],[139.4225686,35.7366797],[139.4227799,35.7369273],[139.4214214,35.7372722],[139.4213175,35.7372214],[139.4208196,35.7356856],[139.4207725,35.735498],[139.4207539,35.7353756],[139.4205485,35.7319114],[139.4206145,35.731831],[139.4209315,35.7317592]]]}},{"type":"Feature","properties":{"name":"伊豆殿公園","distance_m":219,"area_m2":3314,"osm_type":"way","osm_id":559748180,"city":"","note":"市外・小平市境界から500m以内"},"geometry":{"type":"Polygon","coordinates":[[[139.4712554,35.7457789],[139.470588,35.745467],[139.4706381,35.7453434],[139.4706724,35.7451599],[139.471454,35.745248],[139.4712554,35.7457789]]]}},{"type":"Feature","properties":{"name":"上新堀公園","distance_m":229,"area_m2":1400,"osm_type":"way","osm_id":249323019,"city":"","note":"市外・小平市境界から500m以内"},"geometry":{"type":"Polygon","coordinates":[[[139.446034,35.7371745],[139.4454807,35.7371991],[139.4454475,35.7372268],[139.4454378,35.7374589],[139.4457612,35.7373604],[139.4458173,35.7373613],[139.4458653,35.737449],[139.4460174,35.737471],[139.4460316,35.7374293],[139.4460628,35.7371958],[139.446034,35.7371745]]]}},{"type":"Feature","properties":{"name":"東村山中央公園","distance_m":253,"area_m2":110590,"osm_type":"relation","osm_id":905357,"city":"","note":"市外・小平市境界から500m以内"},"geometry":{"type":"Polygon","coordinates":[[[139.4630754,35.7451259],[139.4631504,35.7451587],[139.4631614,35.7452243],[139.4632129,35.745581],[139.4633325,35.7461754],[139.4623581,35.7466046],[139.4626251,35.7470134],[139.4559699,35.7499453],[139.4550786,35.7486398],[139.4555606,35.7484224],[139.4557073,35.7483551],[139.4561157,35.7481626],[139.4565651,35.7481079],[139.4566696,35.748064],[139.4570957,35.7478672],[139.4576711,35.7476035],[139.457848,35.747517],[139.4580643,35.7478251],[139.4594136,35.747169],[139.4591983,35.7468401],[139.4595307,35.7466209],[139.459648,35.7465698],[139.4604244,35.7462363],[139.4612164,35.7459074],[139.4630754,35.7451259]],[[139.4556474,35.7486024],[139.455629,35.7486708],[139.4556505,35.7486844],[139.4556765,35.7487043],[139.4556934,35.7487317],[139.4557041,35.7487553],[139.4557072,35.7487889],[139.4556964,35.7488125],[139.4556811,35.7488287],[139.4556627,35.7488399],[139.4557684,35.7489556],[139.4558619,35.7490302],[139.4559646,35.7492602],[139.4559891,35.749356],[139.4560688,35.7494145],[139.4561393,35.7494493],[139.4562036,35.749458],[139.456337,35.7494455],[139.4564442,35.7494256],[139.4565346,35.7493921],[139.4566235,35.7493386],[139.4567001,35.7492777],[139.4567951,35.7491682],[139.4568626,35.7490886],[139.4569131,35.7489817],[139.4569392,35.748907],[139.4569422,35.7488138],[139.456953,35.7487765],[139.4569622,35.7487454],[139.4569622,35.7487193],[139.4569407,35.748677],[139.456884,35.7486235],[139.4568334,35.7485601],[139.4567951,35.7485165],[139.4567614,35.7485029],[139.4566771,35.7484842],[139.4565668,35.7484432],[139.4564641,35.7484034],[139.4563906,35.7483822],[139.4563109,35.7483685],[139.4562772,35.7483797],[139.4562036,35.7484171],[139.4561209,35.7484506],[139.4560688,35.748483],[139.4559707,35.7485277],[139.4559339,35.748534],[139.4558895,35.7485364],[139.4558604,35.748529],[139.4558267,35.7485203],[139.455796,35.7485203],[139.4557639,35.748529],[139.4557317,35.7485377],[139.4556842,35.7485588],[139.4556597,35.7485812],[139.4556474,35.7486024]]]}},{"type":"Feature","properties":{"name":"向原南公園","distance_m":270,"area_m2":819,"osm_type":"way","osm_id":726612491,"city":"","note":"市外・小平市境界から500m以内"},"geometry":{"type":"Polygon","coordinates":[[[139.4359293,35.7366135],[139.4365248,35.736532],[139.4365318,35.7364941],[139.4359702,35.7363718],[139.4359293,35.7366135]]]}},{"type":"Feature","properties":{"name":"ハンカチの木公園","distance_m":278,"area_m2":328,"osm_type":"way","osm_id":754224515,"city":"","note":"市外・小平市境界から500m以内"},"geometry":{"type":"Polygon","coordinates":[[[139.4301443,35.7338879],[139.4302737,35.7338835],[139.4302597,35.7336183],[139.4301318,35.7336491],[139.4301443,35.7338879]]]}},{"type":"Feature","properties":{"name":"ケヤキ広場","distance_m":291,"area_m2":4258,"osm_type":"way","osm_id":568392686,"city":"","note":"市外・小平市境界から500m以内"},"geometry":{"type":"Polygon","coordinates":[[[139.4909904,35.7057],[139.4908229,35.7047654],[139.4912664,35.704713],[139.4914339,35.7056476],[139.4909904,35.7057]]]}},{"type":"Feature","properties":{"name":"こもれび公園","distance_m":299,"area_m2":101,"osm_type":"way","osm_id":757512355,"city":"","note":"市外・小平市境界から500m以内"},"geometry":{"type":"Polygon","coordinates":[[[139.5082556,35.709857],[139.5082561,35.7098051],[139.5084498,35.7098065],[139.5084493,35.7098583],[139.5082556,35.709857]]]}},{"type":"Feature","properties":{"name":"いけとおがわ プレイパーク","distance_m":307,"area_m2":4978,"osm_type":"relation","osm_id":8098101,"city":"","note":"市外・小平市境界から500m以内"},"geometry":{"type":"Polygon","coordinates":[[[139.4947101,35.7065445],[139.4945763,35.7057813],[139.4952471,35.7057015],[139.4953765,35.7064665],[139.4947101,35.7065445]],[[139.4950893,35.705819],[139.4951094,35.7057874],[139.4951631,35.7057743],[139.4952167,35.70577],[139.4952529,35.7058048],[139.4952489,35.7058429],[139.4952167,35.7058571],[139.4951604,35.705856],[139.4951135,35.7058549],[139.495088,35.7058407],[139.4950772,35.7058603],[139.4950196,35.7058701],[139.4949861,35.7058701],[139.4949364,35.705844],[139.4949029,35.70582],[139.4949203,35.7057934],[139.4949485,35.705771],[139.4950088,35.7057558],[139.4950759,35.7057917],[139.4950893,35.705819]]]}},{"type":"Feature","properties":{"name":"上水公園","distance_m":308,"area_m2":19730,"osm_type":"way","osm_id":792340208,"city":"","note":"市外・小平市境界から500m以内"},"geometry":{"type":"Polygon","coordinates":[[[139.5059775,35.7094834],[139.5058815,35.7086994],[139.5058559,35.7083302],[139.5058523,35.7083008],[139.5057683,35.708308],[139.5044173,35.708411],[139.504473,35.7087899],[139.5044731,35.7089689],[139.5044598,35.7089901],[139.5041879,35.7090139],[139.5042312,35.7093208],[139.5041473,35.7093724],[139.5041645,35.7094737],[139.5042089,35.7097347],[139.5047365,35.7096957],[139.5047224,35.7095896],[139.5059775,35.7094834]]]}},{"type":"Feature","properties":{"name":"向原公園","distance_m":324,"area_m2":1214,"osm_type":"way","osm_id":165192452,"city":"","note":"市外・小平市境界から500m以内"},"geometry":{"type":"Polygon","coordinates":[[[139.4399088,35.7391889],[139.4399439,35.7388288],[139.4397553,35.7388103],[139.4397604,35.7387533],[139.4402103,35.7387855],[139.4401618,35.7392089],[139.4399088,35.7391889]]]}},{"type":"Feature","properties":{"name":"桜町公園","distance_m":350,"area_m2":921,"osm_type":"way","osm_id":742459128,"city":"","note":"市外・小平市境界から500m以内"},"geometry":{"type":"Polygon","coordinates":[[[139.5092376,35.7095485],[139.5095374,35.7095478],[139.5095394,35.7092411],[139.509242,35.7092419],[139.5092376,35.7095485]]]}},{"type":"Feature","properties":{"name":"桜町大尽の坂公園","distance_m":399,"area_m2":52,"osm_type":"way","osm_id":742758113,"city":"","note":"市外・小平市境界から500m以内"},"geometry":{"type":"Polygon","coordinates":[[[139.5108746,35.7097898],[139.5109289,35.7097898],[139.51093,35.7096954],[139.5108746,35.7096959],[139.5108746,35.7097898]]]}},{"type":"Feature","properties":{"name":"幸五公園","distance_m":406,"area_m2":3328,"osm_type":"way","osm_id":943828613,"city":"","note":"市外・小平市境界から500m以内"},"geometry":{"type":"Polygon","coordinates":[[[139.4193357,35.7277353],[139.4191898,35.7269514],[139.4195889,35.7269375],[139.4197434,35.7278084],[139.4195289,35.7277771],[139.4193357,35.7277353]]]}},{"type":"Feature","properties":{"name":"滝山公園","distance_m":407,"area_m2":24024,"osm_type":"way","osm_id":542874443,"city":"東久留米市","note":"市外・小平市境界から500m以内"},"geometry":{"type":"Polygon","coordinates":[[[139.5097602,35.7465694],[139.5089221,35.745216],[139.510346,35.7446456],[139.5108954,35.7455637],[139.5111656,35.74601],[139.5102752,35.7463629],[139.5097602,35.7465694]]]}},{"type":"Feature","properties":{"name":"桜みらい公園","distance_m":412,"area_m2":485,"osm_type":"way","osm_id":754224514,"city":"","note":"市外・小平市境界から500m以内"},"geometry":{"type":"Polygon","coordinates":[[[139.4294493,35.7347951],[139.4298489,35.734814],[139.4299348,35.7348602],[139.4295627,35.7349515],[139.4294557,35.7349007],[139.4294493,35.7347951]]]}},{"type":"Feature","properties":{"name":"南町運動広場多目的運動広場","distance_m":422,"area_m2":4686,"osm_type":"way","osm_id":556775131,"city":"","note":"市外・小平市境界から500m以内"},"geometry":{"type":"Polygon","coordinates":[[[139.5264699,35.7406141],[139.5257566,35.7409729],[139.5254656,35.7405369],[139.5254351,35.7404491],[139.5261406,35.7401456],[139.5264699,35.7406141]]]}},{"type":"Feature","properties":{"name":"上仲原公園","distance_m":429,"area_m2":43090,"osm_type":"way","osm_id":165192451,"city":"","note":"市外・小平市境界から500m以内"},"geometry":{"type":"Polygon","coordinates":[[[139.4427466,35.7426069],[139.4428341,35.7416082],[139.4429394,35.7404049],[139.4429535,35.7402443],[139.4429599,35.7401797],[139.4446208,35.7402245],[139.4446705,35.7402771],[139.4446645,35.7405096],[139.4445708,35.742414],[139.4445595,35.7426443],[139.4434439,35.7426213],[139.4428881,35.7426098],[139.4427466,35.7426069]]]}},{"type":"Feature","properties":{"name":"清原南公園","distance_m":438,"area_m2":1557,"osm_type":"way","osm_id":777899082,"city":"","note":"市外・小平市境界から500m以内"},"geometry":{"type":"Polygon","coordinates":[[[139.4480591,35.7404405],[139.4488394,35.7404469],[139.4488403,35.7404346],[139.4487081,35.7403435],[139.4486112,35.7402576],[139.4485363,35.7401809],[139.4484918,35.7401499],[139.448369,35.7400934],[139.4483008,35.7401042],[139.4480591,35.7404405]]]}},{"type":"Feature","properties":{"name":"さくら公園","distance_m":442,"area_m2":525,"osm_type":"way","osm_id":564628995,"city":"","note":"市外・小平市境界から500m以内"},"geometry":{"type":"Polygon","coordinates":[[[139.5129315,35.7124149],[139.5129346,35.7122069],[139.5131864,35.712211],[139.5131848,35.7124165],[139.5129315,35.7124149]]]}},{"type":"Feature","properties":{"name":"向原中央公園","distance_m":451,"area_m2":13441,"osm_type":"way","osm_id":726614762,"city":"","note":"市外・小平市境界から500m以内"},"geometry":{"type":"Polygon","coordinates":[[[139.4381725,35.7391623],[139.438227,35.7391991],[139.4382471,35.7393151],[139.4382469,35.7394344],[139.4382195,35.739566],[139.4370474,35.7394786],[139.4370708,35.7392775],[139.4363421,35.7392288],[139.4362723,35.7398736],[139.4360742,35.7398746],[139.4360746,35.7397974],[139.4359917,35.739796],[139.4359931,35.7396776],[139.4352392,35.7396633],[139.4352386,35.7394249],[139.4351242,35.7392206],[139.4352027,35.7391556],[139.435297,35.7390893],[139.4354047,35.7390274],[139.4354867,35.7390147],[139.4355688,35.7390173],[139.4361418,35.7390492],[139.4381725,35.7391623]]]}},{"type":"Feature","properties":{"name":"南町第6緑地","distance_m":455,"area_m2":566,"osm_type":"way","osm_id":556775132,"city":"","note":"市外・小平市境界から500m以内"},"geometry":{"type":"Polygon","coordinates":[[[139.5262546,35.7398263],[139.5265128,35.7397042],[139.526403,35.7395524],[139.5261306,35.7396514],[139.5262546,35.7398263]]]}},{"type":"Feature","properties":{"name":"南町第4緑地","distance_m":457,"area_m2":165,"osm_type":"way","osm_id":556775133,"city":"","note":"市外・小平市境界から500m以内"},"geometry":{"type":"Polygon","coordinates":[[[139.526216,35.738381],[139.5262871,35.7383397],[139.5264274,35.7384717],[139.5263298,35.738513],[139.526216,35.738381]]]}},{"type":"Feature","properties":{"name":"滝山公園 テニスコート","distance_m":479,"area_m2":3720,"osm_type":"way","osm_id":542874116,"city":"東久留米市","note":"市外・小平市境界から500m以内"},"geometry":{"type":"Polygon","coordinates":[[[139.5104066,35.7463278],[139.5101626,35.7459447],[139.5109323,35.7456247],[139.5111656,35.74601],[139.5104066,35.7463278]]]}},{"type":"Feature","properties":{"name":"田無市民公園","distance_m":485,"area_m2":9142,"osm_type":"way","osm_id":550912804,"city":"","note":"市外・小平市境界から500m以内"},"geometry":{"type":"Polygon","coordinates":[[[139.5300874,35.7198494],[139.530066,35.7196229],[139.5303516,35.7195984],[139.5307392,35.7195478],[139.5308746,35.7196425],[139.5309149,35.7200857],[139.5309605,35.7203492],[139.5312716,35.7211592],[139.5300311,35.7203394],[139.5300244,35.7202817],[139.5303248,35.7202621],[139.5302819,35.7198407],[139.5300874,35.7198494]]]}},{"type":"Feature","properties":{"name":"本町公園","distance_m":496,"area_m2":2127,"osm_type":"way","osm_id":562641453,"city":"","note":"市外・小平市境界から500m以内"},"geometry":{"type":"Polygon","coordinates":[[[139.5018337,35.7080864],[139.5017524,35.7075213],[139.5021093,35.7074574],[139.5021443,35.7076735],[139.5022019,35.7080299],[139.5018337,35.7080864]]]}}]} \ No newline at end of file
+{"type":"FeatureCollection","features":[{"type":"Feature","properties":{"name":"すみれ公園","distance_m":4,"area_m2":1118,"osm_type":"way","osm_id":542686107,"city":"","note":"市外・小平市境界から500m以内","name_source":"osm"},"geometry":{"type":"Polygon","coordinates":[[[139.49887,35.7458891],[139.4987681,35.745741],[139.4984301,35.7459239],[139.4986072,35.7462004],[139.4988244,35.7460828],[139.4987949,35.7459696],[139.49887,35.7458891]]]}},{"type":"Feature","properties":{"name":"若葉緑地","distance_m":4,"area_m2":3395,"osm_type":"way","osm_id":591305877,"city":"","note":"市外・小平市境界から500m以内","name_source":"osm"},"geometry":{"type":"Polygon","coordinates":[[[139.4348041,35.7255946],[139.4341234,35.7255259],[139.4341039,35.7250579],[139.4344686,35.7250685],[139.4344816,35.7252139],[139.4349962,35.725235],[139.4350255,35.7252958],[139.4348041,35.7255946]]]}},{"type":"Feature","properties":{"name":"あじさい公園","distance_m":5,"area_m2":2317,"osm_type":"way","osm_id":1521995587,"city":"","note":"市外・小平市境界から500m以内","name_source":"osm"},"geometry":{"type":"Polygon","coordinates":[[[139.5066696,35.7418588],[139.5062131,35.7420472],[139.5059587,35.7416542],[139.5064167,35.7414578],[139.5066696,35.7418588]]]}},{"type":"Feature","properties":{"name":"富士見町1丁目第2仲よし広場","distance_m":5,"area_m2":1727,"osm_type":"way","osm_id":965224418,"city":"","note":"市外・小平市境界から500m以内","name_source":"osm"},"geometry":{"type":"Polygon","coordinates":[[[139.4551618,35.7387211],[139.4563827,35.739249],[139.4557987,35.7392483],[139.4557816,35.7390298],[139.4551012,35.7389491],[139.4551099,35.7388152],[139.4551618,35.7387211]]]}},{"type":"Feature","properties":{"name":"青梅橋公園","distance_m":22,"area_m2":388,"osm_type":"way","osm_id":754232094,"city":"","note":"市外・小平市境界から500m以内","name_source":"osm"},"geometry":{"type":"Polygon","coordinates":[[[139.4324421,35.7321674],[139.4327844,35.7321617],[139.4328439,35.7321892],[139.4328557,35.7321666],[139.4324314,35.7319798],[139.4324421,35.7321674]]]}},{"type":"Feature","properties":{"name":"桜が丘一丁目公園","distance_m":28,"area_m2":3067,"osm_type":"way","osm_id":754232096,"city":"","note":"市外・小平市境界から500m以内","name_source":"osm"},"geometry":{"type":"Polygon","coordinates":[[[139.4306727,35.7316731],[139.4314557,35.7316397],[139.4323502,35.7321376],[139.4323444,35.732073],[139.4323392,35.7320163],[139.4323165,35.7319804],[139.430697,35.7312184],[139.4306426,35.7312446],[139.4306727,35.7316731]]]}},{"type":"Feature","properties":{"name":"青梅橋東公園","distance_m":28,"area_m2":148,"osm_type":"way","osm_id":754232095,"city":"","note":"市外・小平市境界から500m以内","name_source":"osm"},"geometry":{"type":"Polygon","coordinates":[[[139.4329793,35.7324124],[139.4332489,35.7324111],[139.4329747,35.7323036],[139.4329793,35.7324124]]]}},{"type":"Feature","properties":{"name":"南台公園","distance_m":34,"area_m2":7777,"osm_type":"way","osm_id":591322526,"city":"","note":"市外・小平市境界から500m以内","name_source":"osm"},"geometry":{"type":"Polygon","coordinates":[[[139.4586433,35.7420302],[139.4591958,35.7420476],[139.4592366,35.7420302],[139.4593017,35.7410812],[139.4591617,35.7410363],[139.4592431,35.7408433],[139.4588588,35.7406583],[139.4586439,35.740986],[139.4586433,35.7420302]]]}},{"type":"Feature","properties":{"name":"用水北緑地","distance_m":51,"area_m2":2199,"osm_type":"way","osm_id":693736574,"city":"","note":"市外・小平市境界から500m以内","name_source":"osm"},"geometry":{"type":"Polygon","coordinates":[[[139.4426016,35.7373346],[139.4426667,35.7367311],[139.4427431,35.736731],[139.4425606,35.7382661],[139.4427828,35.7382803],[139.4427783,35.7383217],[139.4425624,35.7383098],[139.4424377,35.7392776],[139.4424678,35.7393173],[139.4423803,35.7393139],[139.4424744,35.7384284],[139.4423704,35.7384089],[139.4422463,35.7384134],[139.4422664,35.7382484],[139.4425005,35.7382633],[139.4426016,35.7373346]]]}},{"type":"Feature","properties":{"name":"窪東公園","distance_m":56,"area_m2":13725,"osm_type":"way","osm_id":727456979,"city":"","note":"市外・小平市境界から500m以内","name_source":"nearby_node"},"geometry":{"type":"Polygon","coordinates":[[[139.4654475,35.7163836],[139.4661449,35.7151053],[139.4655307,35.7147176],[139.4644605,35.7160374],[139.4654475,35.7163836]]]}},{"type":"Feature","properties":{"name":"富士見町2丁目第2仲よし広場","distance_m":64,"area_m2":76,"osm_type":"way","osm_id":965225385,"city":"","note":"市外・小平市境界から500m以内","name_source":"osm"},"geometry":{"type":"Polygon","coordinates":[[[139.4548178,35.7393066],[139.454867,35.73931],[139.4549317,35.7392079],[139.4548302,35.7392088],[139.4548178,35.7393066]]]}},{"type":"Feature","properties":{"name":"萩山公園","distance_m":69,"area_m2":9856,"osm_type":"way","osm_id":1462182280,"city":"","note":"市外・小平市境界から500m以内","name_source":"osm"},"geometry":{"type":"Polygon","coordinates":[[[139.473544,35.743935],[139.4735794,35.7439436],[139.474243,35.7435759],[139.4737767,35.7426251],[139.4728893,35.743005],[139.4729362,35.7431142],[139.4730193,35.7432377],[139.473544,35.743935]]]}},{"type":"Feature","properties":{"name":"コウヤマキ公園","distance_m":76,"area_m2":234,"osm_type":"way","osm_id":817978652,"city":"","note":"市外・小平市境界から500m以内","name_source":"osm"},"geometry":{"type":"Polygon","coordinates":[[[139.4935696,35.7084541],[139.4935476,35.708332],[139.4937318,35.7083087],[139.4937538,35.708417],[139.4937284,35.7084376],[139.4935696,35.7084541]]]}},{"type":"Feature","properties":{"name":"萩山四季の森公園","distance_m":76,"area_m2":9260,"osm_type":"way","osm_id":375322224,"city":"","note":"市外・小平市境界から500m以内","name_source":"osm"},"geometry":{"type":"Polygon","coordinates":[[[139.4753838,35.7425524],[139.4754466,35.7428113],[139.4754044,35.7430008],[139.474911,35.7431718],[139.4742411,35.7435494],[139.4737718,35.7426025],[139.4742316,35.7424093],[139.4745409,35.7428655],[139.4753838,35.7425524]]]}},{"type":"Feature","properties":{"name":"北町公園","distance_m":77,"area_m2":4613,"osm_type":"way","osm_id":591177446,"city":"","note":"市外・小平市境界から500m以内","name_source":"osm"},"geometry":{"type":"Polygon","coordinates":[[[139.4510419,35.721191],[139.4516704,35.721111],[139.4514732,35.7203655],[139.4510357,35.7204256],[139.4510542,35.7205457],[139.4508817,35.7205657],[139.4510419,35.721191]]]}},{"type":"Feature","properties":{"name":"芝久保三丁目ふれあい公園","distance_m":88,"area_m2":2550,"osm_type":"way","osm_id":1362560908,"city":"","note":"市外・小平市境界から500m以内","name_source":"osm"},"geometry":{"type":"Polygon","coordinates":[[[139.5191406,35.7293977],[139.5191246,35.729057],[139.5189069,35.7290647],[139.5189106,35.7291702],[139.5187826,35.7291731],[139.5187789,35.7290676],[139.5183128,35.7290842],[139.5183419,35.7292174],[139.5183864,35.7294214],[139.5187654,35.7294077],[139.5187763,35.7294125],[139.518822,35.7294106],[139.5191406,35.7293977]]]}},{"type":"Feature","properties":{"name":"北町パンダ公園","distance_m":94,"area_m2":1675,"osm_type":"manual","osm_id":"hokucho-panda","city":"国分寺市","note":"市外・小平市境界から500m以内(公園の範囲は未取得。位置は国分寺市の公園情報による)","name_source":"manual"},"geometry":{"type":"Point","coordinates":[139.447225,35.721831]}},{"type":"Feature","properties":{"name":"萩山公園","distance_m":105,"area_m2":2063,"osm_type":"way","osm_id":558149589,"city":"","note":"市外・小平市境界から500m以内","name_source":"osm"},"geometry":{"type":"Polygon","coordinates":[[[139.4753972,35.7422672],[139.4753234,35.7420898],[139.4752765,35.7419395],[139.4757566,35.7417251],[139.475935,35.74208],[139.4753972,35.7422672]]]}},{"type":"Feature","properties":{"name":"さつき公園","distance_m":113,"area_m2":1974,"osm_type":"way","osm_id":543026519,"city":"","note":"市外・小平市境界から500m以内","name_source":"osm"},"geometry":{"type":"Polygon","coordinates":[[[139.5096639,35.7411551],[139.5094266,35.7407812],[139.5098426,35.7406074],[139.5100752,35.74099],[139.5096639,35.7411551]]]}},{"type":"Feature","properties":{"name":"桜町こぶし公園","distance_m":121,"area_m2":152,"osm_type":"way","osm_id":593771700,"city":"","note":"市外・小平市境界から500m以内","name_source":"osm"},"geometry":{"type":"Polygon","coordinates":[[[139.5094476,35.7133134],[139.5096078,35.7133184],[139.5096113,35.7132257],[139.5094432,35.7132222],[139.5094476,35.7133134]]]}},{"type":"Feature","properties":{"name":"富士見町1丁目第3仲よし広場","distance_m":184,"area_m2":1041,"osm_type":"way","osm_id":668907354,"city":"東村山市","note":"市外・小平市境界から500m以内","name_source":"osm"},"geometry":{"type":"Polygon","coordinates":[[[139.4624137,35.7440997],[139.4619222,35.7440867],[139.4619188,35.7440971],[139.4619148,35.7442438],[139.4619138,35.7442969],[139.4624022,35.7443098],[139.4624137,35.7440997]]]}},{"type":"Feature","properties":{"name":"ひょうたん公園","distance_m":214,"area_m2":3515,"osm_type":"way","osm_id":563674138,"city":"","note":"市外・小平市境界から500m以内","name_source":"osm"},"geometry":{"type":"Polygon","coordinates":[[[139.4974454,35.7085293],[139.497419,35.708478],[139.4973493,35.7082461],[139.4973206,35.708145],[139.4973091,35.7081114],[139.4972735,35.7079576],[139.4972279,35.707808],[139.4975624,35.7077753],[139.4977517,35.7077645],[139.4978495,35.7085013],[139.4976645,35.7085113],[139.4974454,35.7085293]]]}},{"type":"Feature","properties":{"name":"東大和南公園","distance_m":218,"area_m2":100408,"osm_type":"way","osm_id":165197251,"city":"","note":"市外・小平市境界から500m以内","name_source":"osm"},"geometry":{"type":"Polygon","coordinates":[[[139.4209315,35.7317592],[139.4210368,35.7335495],[139.4228427,35.7334823],[139.4251194,35.7333976],[139.4252208,35.7346496],[139.4239703,35.7347091],[139.4222181,35.734803],[139.4222618,35.735362],[139.4224708,35.7353468],[139.4225686,35.7366797],[139.4227799,35.7369273],[139.4214214,35.7372722],[139.4213175,35.7372214],[139.4208196,35.7356856],[139.4207725,35.735498],[139.4207539,35.7353756],[139.4205485,35.7319114],[139.4206145,35.731831],[139.4209315,35.7317592]]]}},{"type":"Feature","properties":{"name":"伊豆殿公園","distance_m":219,"area_m2":3314,"osm_type":"way","osm_id":559748180,"city":"","note":"市外・小平市境界から500m以内","name_source":"osm"},"geometry":{"type":"Polygon","coordinates":[[[139.4712554,35.7457789],[139.470588,35.745467],[139.4706381,35.7453434],[139.4706724,35.7451599],[139.471454,35.745248],[139.4712554,35.7457789]]]}},{"type":"Feature","properties":{"name":"上新堀公園","distance_m":229,"area_m2":1400,"osm_type":"way","osm_id":249323019,"city":"","note":"市外・小平市境界から500m以内","name_source":"osm"},"geometry":{"type":"Polygon","coordinates":[[[139.446034,35.7371745],[139.4454807,35.7371991],[139.4454475,35.7372268],[139.4454378,35.7374589],[139.4457612,35.7373604],[139.4458173,35.7373613],[139.4458653,35.737449],[139.4460174,35.737471],[139.4460316,35.7374293],[139.4460628,35.7371958],[139.446034,35.7371745]]]}},{"type":"Feature","properties":{"name":"東村山中央公園","distance_m":253,"area_m2":110590,"osm_type":"relation","osm_id":905357,"city":"","note":"市外・小平市境界から500m以内","name_source":"osm"},"geometry":{"type":"Polygon","coordinates":[[[139.4630754,35.7451259],[139.4631504,35.7451587],[139.4631614,35.7452243],[139.4632129,35.745581],[139.4633325,35.7461754],[139.4623581,35.7466046],[139.4626251,35.7470134],[139.4559699,35.7499453],[139.4550786,35.7486398],[139.4555606,35.7484224],[139.4557073,35.7483551],[139.4561157,35.7481626],[139.4565651,35.7481079],[139.4566696,35.748064],[139.4570957,35.7478672],[139.4576711,35.7476035],[139.457848,35.747517],[139.4580643,35.7478251],[139.4594136,35.747169],[139.4591983,35.7468401],[139.4595307,35.7466209],[139.459648,35.7465698],[139.4604244,35.7462363],[139.4612164,35.7459074],[139.4630754,35.7451259]],[[139.4556474,35.7486024],[139.455629,35.7486708],[139.4556505,35.7486844],[139.4556765,35.7487043],[139.4556934,35.7487317],[139.4557041,35.7487553],[139.4557072,35.7487889],[139.4556964,35.7488125],[139.4556811,35.7488287],[139.4556627,35.7488399],[139.4557684,35.7489556],[139.4558619,35.7490302],[139.4559646,35.7492602],[139.4559891,35.749356],[139.4560688,35.7494145],[139.4561393,35.7494493],[139.4562036,35.749458],[139.456337,35.7494455],[139.4564442,35.7494256],[139.4565346,35.7493921],[139.4566235,35.7493386],[139.4567001,35.7492777],[139.4567951,35.7491682],[139.4568626,35.7490886],[139.4569131,35.7489817],[139.4569392,35.748907],[139.4569422,35.7488138],[139.456953,35.7487765],[139.4569622,35.7487454],[139.4569622,35.7487193],[139.4569407,35.748677],[139.456884,35.7486235],[139.4568334,35.7485601],[139.4567951,35.7485165],[139.4567614,35.7485029],[139.4566771,35.7484842],[139.4565668,35.7484432],[139.4564641,35.7484034],[139.4563906,35.7483822],[139.4563109,35.7483685],[139.4562772,35.7483797],[139.4562036,35.7484171],[139.4561209,35.7484506],[139.4560688,35.748483],[139.4559707,35.7485277],[139.4559339,35.748534],[139.4558895,35.7485364],[139.4558604,35.748529],[139.4558267,35.7485203],[139.455796,35.7485203],[139.4557639,35.748529],[139.4557317,35.7485377],[139.4556842,35.7485588],[139.4556597,35.7485812],[139.4556474,35.7486024]]]}},{"type":"Feature","properties":{"name":"向原南公園","distance_m":270,"area_m2":819,"osm_type":"way","osm_id":726612491,"city":"","note":"市外・小平市境界から500m以内","name_source":"osm"},"geometry":{"type":"Polygon","coordinates":[[[139.4359293,35.7366135],[139.4365248,35.736532],[139.4365318,35.7364941],[139.4359702,35.7363718],[139.4359293,35.7366135]]]}},{"type":"Feature","properties":{"name":"ハンカチの木公園","distance_m":278,"area_m2":328,"osm_type":"way","osm_id":754224515,"city":"","note":"市外・小平市境界から500m以内","name_source":"osm"},"geometry":{"type":"Polygon","coordinates":[[[139.4301443,35.7338879],[139.4302737,35.7338835],[139.4302597,35.7336183],[139.4301318,35.7336491],[139.4301443,35.7338879]]]}},{"type":"Feature","properties":{"name":"ケヤキ広場","distance_m":291,"area_m2":4258,"osm_type":"way","osm_id":568392686,"city":"","note":"市外・小平市境界から500m以内","name_source":"osm"},"geometry":{"type":"Polygon","coordinates":[[[139.4909904,35.7057],[139.4908229,35.7047654],[139.4912664,35.704713],[139.4914339,35.7056476],[139.4909904,35.7057]]]}},{"type":"Feature","properties":{"name":"こもれび公園","distance_m":299,"area_m2":101,"osm_type":"way","osm_id":757512355,"city":"","note":"市外・小平市境界から500m以内","name_source":"osm"},"geometry":{"type":"Polygon","coordinates":[[[139.5082556,35.709857],[139.5082561,35.7098051],[139.5084498,35.7098065],[139.5084493,35.7098583],[139.5082556,35.709857]]]}},{"type":"Feature","properties":{"name":"いけとおがわ プレイパーク","distance_m":307,"area_m2":4978,"osm_type":"relation","osm_id":8098101,"city":"","note":"市外・小平市境界から500m以内","name_source":"osm"},"geometry":{"type":"Polygon","coordinates":[[[139.4947101,35.7065445],[139.4945763,35.7057813],[139.4952471,35.7057015],[139.4953765,35.7064665],[139.4947101,35.7065445]],[[139.4950893,35.705819],[139.4951094,35.7057874],[139.4951631,35.7057743],[139.4952167,35.70577],[139.4952529,35.7058048],[139.4952489,35.7058429],[139.4952167,35.7058571],[139.4951604,35.705856],[139.4951135,35.7058549],[139.495088,35.7058407],[139.4950772,35.7058603],[139.4950196,35.7058701],[139.4949861,35.7058701],[139.4949364,35.705844],[139.4949029,35.70582],[139.4949203,35.7057934],[139.4949485,35.705771],[139.4950088,35.7057558],[139.4950759,35.7057917],[139.4950893,35.705819]]]}},{"type":"Feature","properties":{"name":"上水公園","distance_m":308,"area_m2":19730,"osm_type":"way","osm_id":792340208,"city":"","note":"市外・小平市境界から500m以内","name_source":"osm"},"geometry":{"type":"Polygon","coordinates":[[[139.5059775,35.7094834],[139.5058815,35.7086994],[139.5058559,35.7083302],[139.5058523,35.7083008],[139.5057683,35.708308],[139.5044173,35.708411],[139.504473,35.7087899],[139.5044731,35.7089689],[139.5044598,35.7089901],[139.5041879,35.7090139],[139.5042312,35.7093208],[139.5041473,35.7093724],[139.5041645,35.7094737],[139.5042089,35.7097347],[139.5047365,35.7096957],[139.5047224,35.7095896],[139.5059775,35.7094834]]]}},{"type":"Feature","properties":{"name":"向原公園","distance_m":324,"area_m2":1214,"osm_type":"way","osm_id":165192452,"city":"","note":"市外・小平市境界から500m以内","name_source":"osm"},"geometry":{"type":"Polygon","coordinates":[[[139.4399088,35.7391889],[139.4399439,35.7388288],[139.4397553,35.7388103],[139.4397604,35.7387533],[139.4402103,35.7387855],[139.4401618,35.7392089],[139.4399088,35.7391889]]]}},{"type":"Feature","properties":{"name":"桜町公園","distance_m":350,"area_m2":921,"osm_type":"way","osm_id":742459128,"city":"","note":"市外・小平市境界から500m以内","name_source":"osm"},"geometry":{"type":"Polygon","coordinates":[[[139.5092376,35.7095485],[139.5095374,35.7095478],[139.5095394,35.7092411],[139.509242,35.7092419],[139.5092376,35.7095485]]]}},{"type":"Feature","properties":{"name":"桜町大尽の坂公園","distance_m":399,"area_m2":52,"osm_type":"way","osm_id":742758113,"city":"","note":"市外・小平市境界から500m以内","name_source":"osm"},"geometry":{"type":"Polygon","coordinates":[[[139.5108746,35.7097898],[139.5109289,35.7097898],[139.51093,35.7096954],[139.5108746,35.7096959],[139.5108746,35.7097898]]]}},{"type":"Feature","properties":{"name":"幸五公園","distance_m":406,"area_m2":3328,"osm_type":"way","osm_id":943828613,"city":"","note":"市外・小平市境界から500m以内","name_source":"osm"},"geometry":{"type":"Polygon","coordinates":[[[139.4193357,35.7277353],[139.4191898,35.7269514],[139.4195889,35.7269375],[139.4197434,35.7278084],[139.4195289,35.7277771],[139.4193357,35.7277353]]]}},{"type":"Feature","properties":{"name":"滝山公園","distance_m":407,"area_m2":24024,"osm_type":"way","osm_id":542874443,"city":"東久留米市","note":"市外・小平市境界から500m以内","name_source":"osm"},"geometry":{"type":"Polygon","coordinates":[[[139.5097602,35.7465694],[139.5089221,35.745216],[139.510346,35.7446456],[139.5108954,35.7455637],[139.5111656,35.74601],[139.5102752,35.7463629],[139.5097602,35.7465694]]]}},{"type":"Feature","properties":{"name":"桜みらい公園","distance_m":412,"area_m2":485,"osm_type":"way","osm_id":754224514,"city":"","note":"市外・小平市境界から500m以内","name_source":"osm"},"geometry":{"type":"Polygon","coordinates":[[[139.4294493,35.7347951],[139.4298489,35.734814],[139.4299348,35.7348602],[139.4295627,35.7349515],[139.4294557,35.7349007],[139.4294493,35.7347951]]]}},{"type":"Feature","properties":{"name":"南町運動広場多目的運動広場","distance_m":422,"area_m2":4686,"osm_type":"way","osm_id":556775131,"city":"","note":"市外・小平市境界から500m以内","name_source":"osm"},"geometry":{"type":"Polygon","coordinates":[[[139.5264699,35.7406141],[139.5257566,35.7409729],[139.5254656,35.7405369],[139.5254351,35.7404491],[139.5261406,35.7401456],[139.5264699,35.7406141]]]}},{"type":"Feature","properties":{"name":"上仲原公園","distance_m":429,"area_m2":43090,"osm_type":"way","osm_id":165192451,"city":"","note":"市外・小平市境界から500m以内","name_source":"osm"},"geometry":{"type":"Polygon","coordinates":[[[139.4427466,35.7426069],[139.4428341,35.7416082],[139.4429394,35.7404049],[139.4429535,35.7402443],[139.4429599,35.7401797],[139.4446208,35.7402245],[139.4446705,35.7402771],[139.4446645,35.7405096],[139.4445708,35.742414],[139.4445595,35.7426443],[139.4434439,35.7426213],[139.4428881,35.7426098],[139.4427466,35.7426069]]]}},{"type":"Feature","properties":{"name":"清原南公園","distance_m":438,"area_m2":1557,"osm_type":"way","osm_id":777899082,"city":"","note":"市外・小平市境界から500m以内","name_source":"osm"},"geometry":{"type":"Polygon","coordinates":[[[139.4480591,35.7404405],[139.4488394,35.7404469],[139.4488403,35.7404346],[139.4487081,35.7403435],[139.4486112,35.7402576],[139.4485363,35.7401809],[139.4484918,35.7401499],[139.448369,35.7400934],[139.4483008,35.7401042],[139.4480591,35.7404405]]]}},{"type":"Feature","properties":{"name":"さくら公園","distance_m":442,"area_m2":525,"osm_type":"way","osm_id":564628995,"city":"","note":"市外・小平市境界から500m以内","name_source":"osm"},"geometry":{"type":"Polygon","coordinates":[[[139.5129315,35.7124149],[139.5129346,35.7122069],[139.5131864,35.712211],[139.5131848,35.7124165],[139.5129315,35.7124149]]]}},{"type":"Feature","properties":{"name":"向原中央公園","distance_m":451,"area_m2":13441,"osm_type":"way","osm_id":726614762,"city":"","note":"市外・小平市境界から500m以内","name_source":"osm"},"geometry":{"type":"Polygon","coordinates":[[[139.4381725,35.7391623],[139.438227,35.7391991],[139.4382471,35.7393151],[139.4382469,35.7394344],[139.4382195,35.739566],[139.4370474,35.7394786],[139.4370708,35.7392775],[139.4363421,35.7392288],[139.4362723,35.7398736],[139.4360742,35.7398746],[139.4360746,35.7397974],[139.4359917,35.739796],[139.4359931,35.7396776],[139.4352392,35.7396633],[139.4352386,35.7394249],[139.4351242,35.7392206],[139.4352027,35.7391556],[139.435297,35.7390893],[139.4354047,35.7390274],[139.4354867,35.7390147],[139.4355688,35.7390173],[139.4361418,35.7390492],[139.4381725,35.7391623]]]}},{"type":"Feature","properties":{"name":"南町第6緑地","distance_m":455,"area_m2":566,"osm_type":"way","osm_id":556775132,"city":"","note":"市外・小平市境界から500m以内","name_source":"osm"},"geometry":{"type":"Polygon","coordinates":[[[139.5262546,35.7398263],[139.5265128,35.7397042],[139.526403,35.7395524],[139.5261306,35.7396514],[139.5262546,35.7398263]]]}},{"type":"Feature","properties":{"name":"南町第4緑地","distance_m":457,"area_m2":165,"osm_type":"way","osm_id":556775133,"city":"","note":"市外・小平市境界から500m以内","name_source":"osm"},"geometry":{"type":"Polygon","coordinates":[[[139.526216,35.738381],[139.5262871,35.7383397],[139.5264274,35.7384717],[139.5263298,35.738513],[139.526216,35.738381]]]}},{"type":"Feature","properties":{"name":"滝山公園 テニスコート","distance_m":479,"area_m2":3720,"osm_type":"way","osm_id":542874116,"city":"東久留米市","note":"市外・小平市境界から500m以内","name_source":"osm"},"geometry":{"type":"Polygon","coordinates":[[[139.5104066,35.7463278],[139.5101626,35.7459447],[139.5109323,35.7456247],[139.5111656,35.74601],[139.5104066,35.7463278]]]}},{"type":"Feature","properties":{"name":"田無市民公園","distance_m":485,"area_m2":9142,"osm_type":"way","osm_id":550912804,"city":"","note":"市外・小平市境界から500m以内","name_source":"osm"},"geometry":{"type":"Polygon","coordinates":[[[139.5300874,35.7198494],[139.530066,35.7196229],[139.5303516,35.7195984],[139.5307392,35.7195478],[139.5308746,35.7196425],[139.5309149,35.7200857],[139.5309605,35.7203492],[139.5312716,35.7211592],[139.5300311,35.7203394],[139.5300244,35.7202817],[139.5303248,35.7202621],[139.5302819,35.7198407],[139.5300874,35.7198494]]]}},{"type":"Feature","properties":{"name":"本町公園","distance_m":496,"area_m2":2127,"osm_type":"way","osm_id":562641453,"city":"","note":"市外・小平市境界から500m以内","name_source":"osm"},"geometry":{"type":"Polygon","coordinates":[[[139.5018337,35.7080864],[139.5017524,35.7075213],[139.5021093,35.7074574],[139.5021443,35.7076735],[139.5022019,35.7080299],[139.5018337,35.7080864]]]}}]}
diff --git a/src/data/park-icons.ts b/src/data/park-icons.ts
new file mode 100644
index 0000000..620df65
--- /dev/null
+++ b/src/data/park-icons.ts
@@ -0,0 +1,15 @@
+// 遊具アイコン(SVGRepo の素材をインライン化)
+export type ParkIcon = { title: string; svg: string };
+export const PARK_ICONS: Record<string, ParkIcon> = {
+ airplane: { title: "ヒコーキジャングル", svg: "<svg viewBox=\"0 0 511.999 511.999\" aria-hidden=\"true\" fill=\"currentColor\"><g>\n\t<g>\n\t\t<path d=\"M492.474,359.413L380.416,247.356c12.062-9.959,11.958-9.813,12.861-10.718c19.26-19.259,27.146-45.418,23.582-70.739\n\t\t\tl11.785-11.786l52.041,52.039c6.511,6.511,17.067,6.511,23.578,0c6.511-6.51,6.511-17.067,0-23.578l-54.069-54.068\n\t\t\tc8.855-18.589,5.609-41.549-9.76-56.919c-15.714-15.714-38.763-18.485-56.94-9.782L329.447,7.759c-6.51-6.51-17.067-6.51-23.578,0\n\t\t\tc-6.511,6.51-6.511,17.067,0,23.578l52.04,52.041l-11.787,11.786c-25.318-3.561-51.47,4.314-70.737,23.582\n\t\t\tc-0.894,0.894-0.757,0.799-10.717,12.862c-0.993-0.994-109.805-109.806-112.059-112.061C126.547-6.513,84.361-6.519,58.295,19.549\n\t\t\tc-26.065,26.063-26.067,68.247,0,94.313c5.315,5.315,115.771,115.772,121.066,121.067l-55.682,67.439\n\t\t\tc-31.857-15.372-70.047-9.028-95.196,16.121L4.906,342.068c-6.511,6.511-6.511,17.067,0,23.578\n\t\t\tc106.734,106.732,37.325,37.326,141.471,141.47c6.511,6.511,17.067,6.511,23.578,0l23.578-23.578\n\t\t\tc25.114-25.113,31.512-63.294,16.122-95.195l67.439-55.682c20.182,20.182,103.593,103.594,121.065,121.066\n\t\t\tc26.003,26.003,68.312,26.005,94.314,0C518.477,427.724,518.477,385.416,492.474,359.413z M393.277,95.167\n\t\t\tc6.517-6.517,17.062-6.517,23.578,0c6.501,6.501,6.501,17.078,0,23.579l-12.966,12.966c-3.064-4.615-6.607-8.96-10.613-12.966\n\t\t\ts-8.352-7.549-12.967-10.613L393.277,95.167z M81.873,43.127c13-13.001,34.155-13.002,47.158-0.001L81.873,90.284\n\t\t\tC68.84,77.25,68.841,56.162,81.873,43.127z M105.452,113.862l47.158-47.158l23.578,23.578l-47.158,47.158L105.452,113.862z\n\t\t\t M152.608,161.019l47.158-47.157l43.575,43.576l-42.654,51.66L152.608,161.019z M62.672,376.257l-22.399-22.399l11.789-11.791\n\t\t\tc13.101-13.1,32.219-17.515,49.282-12.648L62.672,376.257z M169.956,459.961l-11.79,11.789l-22.399-22.399l46.838-38.671\n\t\t\tC187.472,427.743,183.056,446.859,169.956,459.961z M112.082,425.664l-25.724-25.724c8.147-9.867,204.411-247.571,213.132-258.134\n\t\t\tc19.574-19.021,50.827-18.863,70.209,0.518c19.379,19.379,19.541,50.632,0.519,70.209\n\t\t\tC359.671,221.241,121.995,417.479,112.082,425.664z M351.004,359.415l-48.078-48.079l51.66-42.654l43.575,43.575L351.004,359.415z\n\t\t\t M374.582,382.994l47.158-47.158l23.579,23.579l-47.158,47.157L374.582,382.994z M468.896,430.15\n\t\t\tc-13.001,12.998-34.155,13.001-47.158,0l47.158-47.157C481.896,395.995,481.896,417.149,468.896,430.15z\"/>\n\t</g>\n</g>\n<g>\n\t<g>\n\t\t<path d=\"M322.541,189.481c-6.51-6.51-17.067-6.51-23.578,0l-70.736,70.736c-6.511,6.51-6.511,17.067,0,23.578\n\t\t\tc3.256,3.256,7.523,4.884,11.79,4.884c4.267,0,8.534-1.628,11.789-4.884l70.736-70.736\n\t\t\tC329.053,206.549,329.053,195.992,322.541,189.481z\"/>\n\t</g>\n</g></svg>" },
+ climbing: { title: "ジャングルジム", svg: "<svg viewBox=\"0 0 24 24\" aria-hidden=\"true\" fill=\"currentColor\"><defs><style>.climb-cls-1{fill:none;stroke:currentColor;stroke-miterlimit:10;stroke-width:1.91px;}</style></defs><line class=\"climb-cls-1\" x1=\"1.5\" y1=\"0.55\" x2=\"1.5\" y2=\"23.45\"/><line class=\"climb-cls-1\" x1=\"12\" y1=\"0.55\" x2=\"12\" y2=\"23.45\"/><line class=\"climb-cls-1\" x1=\"22.5\" y1=\"6.27\" x2=\"22.5\" y2=\"23.45\"/><line class=\"climb-cls-1\" x1=\"1.5\" y1=\"2.45\" x2=\"12\" y2=\"2.45\"/><line class=\"climb-cls-1\" x1=\"1.5\" y1=\"6.27\" x2=\"12\" y2=\"6.27\"/><line class=\"climb-cls-1\" x1=\"1.5\" y1=\"10.09\" x2=\"12\" y2=\"10.09\"/><line class=\"climb-cls-1\" x1=\"1.5\" y1=\"13.91\" x2=\"12\" y2=\"13.91\"/><line class=\"climb-cls-1\" x1=\"1.5\" y1=\"17.73\" x2=\"12\" y2=\"17.73\"/><line class=\"climb-cls-1\" x1=\"1.5\" y1=\"21.55\" x2=\"12\" y2=\"21.55\"/><line class=\"climb-cls-1\" x1=\"12\" y1=\"8.18\" x2=\"22.5\" y2=\"8.18\"/><line class=\"climb-cls-1\" x1=\"12\" y1=\"12\" x2=\"22.5\" y2=\"12\"/><line class=\"climb-cls-1\" x1=\"12\" y1=\"15.82\" x2=\"22.5\" y2=\"15.82\"/><line class=\"climb-cls-1\" x1=\"12\" y1=\"19.64\" x2=\"22.5\" y2=\"19.64\"/></svg>" },
+ swing: { title: "ブランコ", svg: "<svg viewBox=\"0 0 430 430\" aria-hidden=\"true\" fill=\"currentColor\"><path d=\"M412,410h-16V54.09C396,31.984,378.016,14,355.91,14h-67.432v-4c0-5.523-4.478-10-10-10s-10,4.477-10,10v4H161.521v-4 c0-5.523-4.477-10-10-10s-10,4.477-10,10v4H74.09C51.984,14,34,31.984,34,54.09V410H18c-5.523,0-10,4.477-10,10s4.477,10,10,10h52 c5.523,0,10-4.477,10-10s-4.477-10-10-10H54V54.09C54,43.012,63.012,34,74.09,34h67.432v314c0,5.523,4.477,10,10,10h126.958 c5.522,0,10-4.477,10-10V34h67.432C366.988,34,376,43.012,376,54.09V410h-16c-5.522,0-10,4.477-10,10s4.478,10,10,10h52 c5.522,0,10-4.477,10-10S417.523,410,412,410z M161.521,338v-13.383h106.958V338H161.521z M268.479,304.617H161.521V34h106.958 V304.617z\"/></svg>" },
+ teeter: { title: "シーソー", svg: "<svg viewBox=\"0 0 493.927 493.927\" aria-hidden=\"true\" fill=\"currentColor\"><g>\n\t<path d=\"M38.758,234.499c16.794-4.117,27.073-21.056,22.956-37.851c-4.108-16.801-21.048-27.074-37.842-22.965\n\t\tC7.072,177.801-3.209,194.74,0.907,211.534C5.025,228.337,21.964,238.607,38.758,234.499z\"/>\n\t<path d=\"M400.077,146.024c16.803-4.109,27.073-21.057,22.957-37.842c-4.11-16.802-21.049-27.074-37.835-22.965\n\t\tc-16.809,4.117-27.073,21.048-22.964,37.85C366.351,139.861,383.291,150.141,400.077,146.024z\"/>\n\t<path d=\"M493.565,256.893c-1.646-6.725-8.503-10.825-15.138-9.188l-19.46,4.77c0.327-1.818,0.205-3.71-0.098-5.618\n\t\tc-0.978-4.075-18.383-76.988-19.817-80.91c-2.593-11.021-16.6-18.929-29.381-15.823c-12.457,3.057-20.307,14.942-18.773,27.366\n\t\tl-38.96,37.369c-6.651,6.384-6.872,16.949-0.489,23.609c1.06,1.1,2.365,1.736,3.62,2.478c-5.25,2.005-8.421,7.484-7.044,13.084\n\t\tl5.91,24.155l-84.064,20.576c-5.333-5.698-12.865-9.31-21.285-9.31c-13.41,0-24.58,9.074-28.018,21.384l-79.826,19.549\n\t\tl-5.919-24.163c-1.36-5.528-6.563-8.951-12.064-8.365c0.725-1.199,1.435-2.421,1.851-3.831c2.584-8.853-2.495-18.122-11.34-20.714\n\t\tl-51.831-15.146c-4.387-11.732-16.786-18.677-29.3-15.596c-12.627,3.09-21.528,16.532-18.749,27.571\n\t\tc0.538,3.994,19.809,80.942,19.809,80.942c0.611,1.826,1.37,3.563,2.504,5.014l-19.445,4.762\n\t\tc-6.716,1.646-10.833,8.421-9.185,15.138c1.654,6.767,8.486,10.825,15.138,9.187l64.491-15.79l-3.146,19.916\n\t\tc-1.435,9.114,4.776,17.657,13.884,19.1c9.179,1.434,17.673-4.827,19.1-13.882l5.331-33.742l102.953-25.207\n\t\tc2.202,3.082,4.974,5.698,8.169,7.728l-24.961,39.448c-3.408,5.396-3.62,12.211-0.54,17.804c3.074,5.585,8.952,9.058,15.327,9.058\n\t\th51.538c6.376,0,12.253-3.473,15.327-9.058c3.081-5.593,2.869-12.408-0.539-17.804l-24.961-39.448\n\t\tc7.076-4.493,12.008-11.927,13.215-20.601l107.331-26.273l20.307,27.456c5.486,7.409,15.938,8.967,23.355,3.498\n\t\tc7.411-5.486,8.975-15.946,3.497-23.357l-11.992-16.206l64.483-15.791C491.096,270.384,495.211,263.609,493.565,256.893z\n\t\t M399.824,215.202l6.375,26.013l-28.377,6.954c-2.666,0.653-5.07,1.948-7.061,3.71l-0.789-3.227\n\t\tc-0.563-2.308-1.932-4.118-3.58-5.593c3.139-0.563,6.196-1.729,8.667-4.101L399.824,215.202z M108.589,306.043\n\t\tc1.647,0,3.245-0.311,4.784-0.775c-0.701,1.988-1.043,4.124-0.496,6.334l0.79,3.219c-2.576-0.636-5.307-0.676-7.972-0.023\n\t\tl-28.386,6.946l-6.368-26.014C74.839,296.87,104.856,306.043,108.589,306.043z\"/>\n</g></svg>" },
+ spring: { title: "スプリング遊具", svg: "<svg viewBox=\"0 0 512 512\" aria-hidden=\"true\" fill=\"currentColor\"><rect x=\"99.667\" y=\"143.442\" style=\"fill:#FFE97C;\" width=\"307.853\" height=\"106.786\"/>\n<g>\n\t<polygon style=\"fill:#FFF6CC;\" points=\"99.669,238.684 99.669,154.986 10.199,173.265 10.199,220.405 \t\"/>\n\t<path style=\"fill:#FFF6CC;\" d=\"M132.379,94.377h-32.71l25.013,49.064h56.761l0,0C181.442,116.344,159.476,94.377,132.379,94.377z\"\n\t\t/>\n\t<path style=\"fill:#FFF6CC;\" d=\"M132.379,299.292h-32.71l25.013-49.064h56.761l0,0C181.442,277.326,159.476,299.292,132.379,299.292\n\t\tz\"/>\n</g>\n<g>\n\t<polygon style=\"fill:#FF9ECA;\" points=\"501.801,196.834 407.521,152.864 407.521,240.805 \t\"/>\n\t<path style=\"fill:#FF9ECA;\" d=\"M297.38,170.379h-87.571c-14.877,0-26.937-12.061-26.937-26.937l0,0h141.446l0,0\n\t\tC324.317,158.318,312.258,170.379,297.38,170.379z\"/>\n</g>\n<path style=\"fill:#FFE97C;\" d=\"M301.697,422.433h-103.9c-7.97,0-14.431-6.461-14.431-14.431l0,0c0-7.97,6.461-14.431,14.431-14.431\n\th103.9c7.97,0,14.431,6.461,14.431,14.431l0,0C316.127,415.971,309.666,422.433,301.697,422.433z\"/>\n<g>\n\t<path style=\"fill:#4D1E1E;\" d=\"M176.632,186.155h-5.773c-5.633,0-10.199,4.566-10.199,10.199c0,5.633,4.566,10.199,10.199,10.199\n\t\th5.773c5.633,0,10.199-4.566,10.199-10.199C186.831,190.721,182.265,186.155,176.632,186.155z\"/>\n\t<path style=\"fill:#4D1E1E;\" d=\"M190.746,133.242c-4.851-27.833-29.168-49.064-58.367-49.064H99.67\n\t\tc-3.548,0-6.843,1.845-8.697,4.871s-2.001,6.799-0.39,9.961l17.452,34.233H99.67c-5.633,0-10.199,4.566-10.199,10.199v3.219\n\t\tL8.158,163.272C3.41,164.242,0,168.418,0,173.265v47.14c0,4.846,3.41,9.023,8.158,9.993l81.312,16.611v3.219\n\t\tc0,5.633,4.566,10.199,10.199,10.199h8.365L90.583,294.66c-1.611,3.162-1.465,6.934,0.39,9.961\n\t\tc1.854,3.026,5.148,4.871,8.697,4.871h32.709c29.199,0,53.516-21.232,58.367-49.064h52.284c0.056,0.027,0.107,0.058,0.164,0.084\n\t\tl9.186,4.083l-34.814,5.247c-6.176,0.931-10.66,5.94-10.904,12.181c-0.244,6.242,3.835,11.585,9.92,12.997\n\t\tc0.058,0.013,0.116,0.027,0.174,0.039l25.064,5.351l-25.077,4.551c-0.05,0.009-0.101,0.019-0.151,0.029\n\t\tc-6.091,1.2-10.346,6.375-10.346,12.583c0,6.208,4.253,11.383,10.345,12.585c0.05,0.01,0.102,0.019,0.152,0.029l25.098,4.555\n\t\tl-25.862,5.526c-0.057,0.012-0.115,0.025-0.172,0.039c-6.014,1.395-10.096,6.679-9.924,12.852\n\t\tc0.172,6.172,4.541,11.221,10.623,12.279l43.458,7.559l-17.067,10.38h-45.099c-13.581,0-24.63,11.049-24.63,24.629\n\t\tc0,13.581,11.049,24.63,24.63,24.63h103.9c13.581,0,24.63-11.049,24.63-24.63c0-13.58-11.049-24.629-24.63-24.629h-19.548\n\t\tl5.636-3.428c4.611-2.804,6.943-8.042,5.938-13.345c-1.004-5.303-5.088-9.326-10.404-10.249l-24.81-4.314l25.126-5.369\n\t\tc0.057-0.012,0.115-0.026,0.172-0.039c5.947-1.379,10.029-6.605,9.927-12.708c-0.102-6.103-4.356-11.191-10.345-12.371\n\t\tc-0.05-0.01-0.1-0.019-0.15-0.029l-21.766-3.951l21.766-3.95c0.05-0.009,0.101-0.019,0.15-0.029\n\t\tc5.99-1.18,10.243-6.267,10.345-12.371c0.102-6.103-3.981-11.329-9.927-12.708c-0.058-0.013-0.116-0.027-0.174-0.039l-21.866-4.667\n\t\tl19.313-2.911c5.689-0.857,10.029-5.264,10.799-10.965c0.472-3.494-0.482-6.871-2.499-9.503h118.139\n\t\tc5.633,0,10.199-4.566,10.199-10.199v-2.925l88.391-41.224c3.592-1.676,5.888-5.28,5.888-9.244s-2.296-7.568-5.888-9.244\n\t\tl-88.391-41.224v-2.925c0-5.633-4.566-10.199-10.199-10.199h-39.827V99.767h2.307c5.633,0,10.199-4.566,10.199-10.199\n\t\tc0-5.633-4.566-10.199-10.199-10.199h-26.937c-5.633,0-10.199,4.566-10.199,10.199c0,5.633,4.566,10.199,10.199,10.199h4.232\n\t\tv33.476H190.746z M305.928,408.002c0,2.334-1.898,4.232-4.232,4.232H197.797c-2.334,0-4.232-1.898-4.232-4.232\n\t\tc0-2.334,1.898-4.231,4.232-4.231h103.9C304.03,403.771,305.928,405.669,305.928,408.002z M109.868,206.553h28.282\n\t\tc5.633,0,10.199-4.566,10.199-10.199c0-5.633-4.566-10.199-10.199-10.199h-28.282v-32.514h64.241\n\t\tc4.445,15.531,18.761,26.937,35.7,26.937h87.571c16.94,0,31.256-11.405,35.7-26.937h64.241v86.387H109.868V206.553z\n\t\t M310.644,153.641c-3.063,3.974-7.87,6.539-13.263,6.539H209.81c-5.394,0-10.2-2.565-13.263-6.539H310.644z M116.316,104.577\n\t\th16.062c17.903,0,33.017,12.167,37.508,28.666H130.93L116.316,104.577z M89.469,167.479v18.675H20.398v-4.563L89.469,167.479z\n\t\t M20.398,212.078v-5.525h69.071v19.637L20.398,212.078z M132.378,289.092h-16.062l14.614-28.666h38.955\n\t\tC165.394,276.927,150.28,289.092,132.378,289.092z M417.721,224.795v-55.92l59.951,27.96L417.721,224.795z\"/>\n</g></svg>" },
+ slide: { title: "滑り台", svg: "<svg viewBox=\"0 0 32 32\" aria-hidden=\"true\" fill=\"currentColor\"><style type=\"text/css\">\n\t.slide-bentblocks_een{fill:#0B1719;}\n</style>\n<path class=\"slide-bentblocks_een\" d=\"M12,4H4v20h2v-2h4v2h2v-8.114L20,28h8L12,4z M6,6.801L6.792,8H6V6.801z M6,10h2.113l1.321,2H6V10z\n\t M10,20H6v-2h4V20z M10,16H6v-2h4V16z M7.868,6h3.062l13.333,20h-3.187L7.868,6z\"/></svg>" },
+ flyingfox: { title: "ロープウェイ", svg: "<svg viewBox=\"0 0 512 512\" aria-hidden=\"true\" fill=\"currentColor\"><path fill=\"currentColor\" d=\"M46.244 18l170.172 72.932 7.586 18.982L242.18 155.4l26.775 11.487-4.412 49.513c3.896-2.256 7.913-4.446 12.102-6.49l.685-.334.733-.215a38.637 38.637 0 0 1 5.28-1.15l3.018-33.858 21.488 9.216 64.54-25.793L494 209.895v-19.583L352.756 129.78c10.44-5.566 17.607-16.574 17.607-29.145 0-18.12-14.88-33-33-33-8.92 0-17.05 3.61-23.01 9.433 0-.145.01-.288.01-.433 0-18.12-14.88-33-33-33-18.12 0-33 14.88-33 33 0 3.096.443 6.093 1.254 8.94L91.937 18H46.245zm235.12 43.635c8.39 0 15 6.61 15 15s-6.61 15-15 15c-8.392 0-15-6.61-15-15s6.608-15 15-15zm56 24c8.39 0 15 6.61 15 15s-6.61 15-15 15c-8.392 0-15-6.61-15-15s6.608-15 15-15zm-32.99 14.566c0 .146-.01.29-.01.435 0 3.096.442 6.093 1.253 8.94l-8.86-3.796a33.383 33.383 0 0 0 7.618-5.58zm-55.595 23.212l77.7 33.328-18.388 7.348-51.965-22.29-7.348-18.386zm-88.813 44.465c-1.564.03-3.078.278-4.53.736-5.804 1.835-10.49 6.994-13.12 15.508-2.627 8.515-2.697 19.943.974 31.56 3.672 11.617 10.297 20.93 17.34 26.386 7.045 5.457 13.845 6.983 19.65 5.15 5.804-1.836 10.49-6.993 13.118-15.507 2.63-8.515 2.7-19.943-.972-31.56-3.672-11.617-10.296-20.927-17.34-26.384-5.283-4.093-10.428-5.977-15.12-5.89zm128.265 57.992c-1.4.004-2.946.266-4.543.68-16.685 8.293-31.973 20.153-49.28 29.423-17.458 9.35-37.674 15.72-61.853 10.865-11.962-1.176-16.464 4.17-17.71 9.943-1.218 5.632.82 12.564 11.155 16.76 55.347 5.065 101.237-31.265 126.685-52.144.002 0 0-.002.002-.003 4.028-3.38 5.42-6.192 5.8-7.913.38-1.72.105-2.63-.76-3.83-1.296-1.8-4.77-3.796-9.498-3.78zm-115.675 40.968c.095.01.18.01.277.02l-.883-.137c.204.043.404.077.607.118zm104.746 9.178c-5.806 4.074-12.11 8.176-18.862 12.086 4.013 9.28 7.354 19.894 9.945 31.99 1.61.113 3.294.26 4.955.398l3.963-44.474zm-34.82 20.457c-20.36 9.566-43.922 16.344-69.917 15.54 2.902 4.44 6.194 8.82 9.725 13.038 5.8 6.925 12.3 13.454 18.59 19.218 7.647-1.047 19.705-4.422 30-9.143 6.385-2.927 12.267-6.335 16.405-9.57a29.504 29.504 0 0 0 3.274-2.98c-2.216-10.03-4.95-18.662-8.078-26.102zm17.345 42.033c-.493.404-.95.832-1.457 1.228-5.738 4.487-12.654 8.39-19.985 11.752-6.59 3.022-13.37 5.63-19.96 7.563 5.682 4.404 9.88 7.312 11.093 8.052 8.19 5.004 20.968 8.01 34.627 9.54 3.935-12.394.912-24.61-4.317-38.136zm19.342.512c4.085 12.243 6.466 25.26 3.312 38.824 2.596.06 5.167.077 7.684.05 21.71-.245 39.418-2.925 39.418-2.925l14.576-2.213-4.693 13.976c-7.496 22.323-10.164 38.087-17.156 59.038l55.614 24.933 9.418-18.973-39.594-16.97 4.678-8.667c3.575-6.625 9.348-20.202 13.79-33.983 3.962-12.288 6.61-24.973 6.827-32.623-.047-.03-.026-.033-.076-.062-1.7-1.004-4.682-2.357-8.45-3.71-7.535-2.71-18.256-5.546-30.214-8.087-17.38-3.692-37.464-6.792-55.133-8.607zm32.142 55.933c-5.626.428-12.035.78-18.986.905l-26.097 43.653 35.194 11.67 1.342-3.64a265.75 265.75 0 0 0 4.83-14.364l-14.076-5.15 17.793-33.073z\"/></svg>" },
+ sand: { title: "砂場", svg: "<svg viewBox=\"0 0 100 100\" aria-hidden=\"true\" fill=\"currentColor\"><g stroke-width=\"0\"/>\n\n<g stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke=\"currentColor\" stroke-width=\"2\"> <g/> <g/> <g/> <g/> <g/> <g/> <g/> <g/> <g/> <g/> <g/> <g> <g> <path d=\"M92.3,8.2C92.2,8,92,7.8,91.8,7.7C76,0.6,57.2,4.1,45,16.3L25.8,35.4c-0.4,0.4-0.4,1,0,1.4l12.6,12.6l-4.8,4.8 c-1.5-1.4-4-1.3-5.5,0.1L4.9,77.7c-1.6,1.6-1.6,4.1,0,5.7l11.8,11.8c0.8,0.8,1.8,1.2,2.8,1.2s2.1-0.4,2.8-1.2l23.3-23.3 c1.5-1.5,1.5-3.9,0.1-5.5l4.8-4.8l12.6,12.6c0.2,0.2,0.5,0.3,0.7,0.3s0.5-0.1,0.7-0.3L83.7,55C95.9,42.8,99.4,24,92.3,8.2z M44.3,64.9l-9.3-9.2l5.5-5.5c0,0,0,0,0,0s0,0,0,0l2.3-2.3c0.8-0.8,2.1-0.8,2.8,0l6.4,6.4c0.8,0.8,0.8,2,0,2.8L44.3,64.9z M44.2,70.4L20.8,93.7c-0.8,0.8-2.1,0.8-2.8,0L6.3,82c-0.8-0.8-0.8-2,0-2.8l23.3-23.3c0.4-0.4,0.9-0.6,1.4-0.6s1,0.2,1.4,0.6 l0.5,0.5l0,0l10.7,10.7c0,0,0,0,0,0l0.5,0.5C44.9,68.4,44.9,69.6,44.2,70.4z M82.3,53.6L63.9,72L52,60.1l1.6-1.6 c1.6-1.6,1.6-4.1,0-5.7l-6.4-6.4c-1.5-1.5-4.1-1.5-5.7,0L39.9,48L28,36.1l18.4-18.4C57.9,6.1,75.7,2.8,90.7,9.3 C97.2,24.3,93.9,42.1,82.3,53.6z\"/> <path d=\"M85.7,13c-0.5,0.2-0.7,0.8-0.5,1.3c5.1,11.4,2.5,25-6.4,33.9c-0.4,0.4-0.4,1,0,1.4c0.2,0.2,0.5,0.3,0.7,0.3 s0.5-0.1,0.7-0.3c9.5-9.5,12.2-24,6.8-36.2C86.8,13,86.2,12.8,85.7,13z\"/> <path d=\"M13.9,80.7c-0.4-0.4-1-0.4-1.4,0s-0.4,1,0,1.4l5.3,5.3c0.2,0.2,0.5,0.3,0.7,0.3s0.5-0.1,0.7-0.3c0.4-0.4,0.4-1,0-1.4 L13.9,80.7z\"/> <path d=\"M17.5,77.2c-0.4-0.4-1-0.4-1.4,0s-0.4,1,0,1.4l5.3,5.3c0.2,0.2,0.5,0.3,0.7,0.3s0.5-0.1,0.7-0.3c0.4-0.4,0.4-1,0-1.4 L17.5,77.2z\"/> <path d=\"M21,73.6c-0.4-0.4-1-0.4-1.4,0s-0.4,1,0,1.4l5.3,5.3c0.2,0.2,0.5,0.3,0.7,0.3s0.5-0.1,0.7-0.3c0.4-0.4,0.4-1,0-1.4 L21,73.6z\"/> </g> </g> <g/> <g/> <g/> <g/> <g/> <g/> <g/> <g/> </g>\n\n<g> <g/> <g/> <g/> <g/> <g/> <g/> <g/> <g/> <g/> <g/> <g/> <g> <g> <path d=\"M92.3,8.2C92.2,8,92,7.8,91.8,7.7C76,0.6,57.2,4.1,45,16.3L25.8,35.4c-0.4,0.4-0.4,1,0,1.4l12.6,12.6l-4.8,4.8 c-1.5-1.4-4-1.3-5.5,0.1L4.9,77.7c-1.6,1.6-1.6,4.1,0,5.7l11.8,11.8c0.8,0.8,1.8,1.2,2.8,1.2s2.1-0.4,2.8-1.2l23.3-23.3 c1.5-1.5,1.5-3.9,0.1-5.5l4.8-4.8l12.6,12.6c0.2,0.2,0.5,0.3,0.7,0.3s0.5-0.1,0.7-0.3L83.7,55C95.9,42.8,99.4,24,92.3,8.2z M44.3,64.9l-9.3-9.2l5.5-5.5c0,0,0,0,0,0s0,0,0,0l2.3-2.3c0.8-0.8,2.1-0.8,2.8,0l6.4,6.4c0.8,0.8,0.8,2,0,2.8L44.3,64.9z M44.2,70.4L20.8,93.7c-0.8,0.8-2.1,0.8-2.8,0L6.3,82c-0.8-0.8-0.8-2,0-2.8l23.3-23.3c0.4-0.4,0.9-0.6,1.4-0.6s1,0.2,1.4,0.6 l0.5,0.5l0,0l10.7,10.7c0,0,0,0,0,0l0.5,0.5C44.9,68.4,44.9,69.6,44.2,70.4z M82.3,53.6L63.9,72L52,60.1l1.6-1.6 c1.6-1.6,1.6-4.1,0-5.7l-6.4-6.4c-1.5-1.5-4.1-1.5-5.7,0L39.9,48L28,36.1l18.4-18.4C57.9,6.1,75.7,2.8,90.7,9.3 C97.2,24.3,93.9,42.1,82.3,53.6z\"/> <path d=\"M85.7,13c-0.5,0.2-0.7,0.8-0.5,1.3c5.1,11.4,2.5,25-6.4,33.9c-0.4,0.4-0.4,1,0,1.4c0.2,0.2,0.5,0.3,0.7,0.3 s0.5-0.1,0.7-0.3c9.5-9.5,12.2-24,6.8-36.2C86.8,13,86.2,12.8,85.7,13z\"/> <path d=\"M13.9,80.7c-0.4-0.4-1-0.4-1.4,0s-0.4,1,0,1.4l5.3,5.3c0.2,0.2,0.5,0.3,0.7,0.3s0.5-0.1,0.7-0.3c0.4-0.4,0.4-1,0-1.4 L13.9,80.7z\"/> <path d=\"M17.5,77.2c-0.4-0.4-1-0.4-1.4,0s-0.4,1,0,1.4l5.3,5.3c0.2,0.2,0.5,0.3,0.7,0.3s0.5-0.1,0.7-0.3c0.4-0.4,0.4-1,0-1.4 L17.5,77.2z\"/> <path d=\"M21,73.6c-0.4-0.4-1-0.4-1.4,0s-0.4,1,0,1.4l5.3,5.3c0.2,0.2,0.5,0.3,0.7,0.3s0.5-0.1,0.7-0.3c0.4-0.4,0.4-1,0-1.4 L21,73.6z\"/> </g> </g> <g/> <g/> <g/> <g/> <g/> <g/> <g/> <g/> </g></svg>" },
+ playground: { title: "複合遊具", svg: "<svg viewBox=\"0 0 512.001 512.001\" aria-hidden=\"true\" fill=\"currentColor\"><g>\n\t<g>\n\t\t<path d=\"M501.335,170.587h-352v-21.333h10.667c4.181,0,7.979-2.453,9.728-6.251c1.728-3.819,1.067-8.299-1.685-11.435\n\t\t\tL93.377,46.235c-4.053-4.651-12.011-4.651-16.064,0L2.647,131.569c-2.752,3.157-3.435,7.616-1.685,11.435\n\t\t\tc1.728,3.797,5.525,6.251,9.707,6.251h10.667v309.333c0,5.888,4.779,10.667,10.667,10.667s10.667-4.779,10.667-10.667v-10.667\n\t\t\th85.333v10.667c0,5.888,4.779,10.667,10.667,10.667s10.667-4.779,10.667-10.667V191.921h64V300.55\n\t\t\tc-12.395,4.416-21.333,16.149-21.333,30.037c0,17.643,14.357,32,32,32s32-14.357,32-32c0-13.888-8.939-25.621-21.333-30.037\n\t\t\tV191.921h85.333v87.296c-12.395,4.416-21.333,16.149-21.333,30.037c0,17.643,14.357,32,32,32c17.643,0,32-14.357,32-32\n\t\t\tc0-13.888-8.939-25.621-21.333-30.037v-87.296h64v266.667c0,5.888,4.779,10.667,10.667,10.667c5.888,0,10.667-4.779,10.667-10.667\n\t\t\tV191.921h42.667v23.573c-6.4,2.667-10.667,7.531-10.667,13.76c0,6.229,4.267,11.093,10.667,13.76v31.147\n\t\t\tc-6.4,2.667-10.667,7.531-10.667,13.76s4.267,11.093,10.667,13.76v31.147c-6.4,2.667-10.667,7.531-10.667,13.76\n\t\t\tc0,6.229,4.267,11.093,10.667,13.76v31.147c-6.4,2.667-10.667,7.531-10.667,13.76c0,6.229,4.267,11.093,10.667,13.76v18.24\n\t\t\tc0,5.888,4.779,10.667,10.667,10.667c5.888,0,10.667-4.779,10.667-10.667v-18.24c6.4-2.667,10.667-7.531,10.667-13.76\n\t\t\tc0-6.229-4.267-11.093-10.667-13.76v-31.147c6.4-2.667,10.667-7.531,10.667-13.76c0-6.229-4.267-11.093-10.667-13.76v-31.147\n\t\t\tc6.4-2.667,10.667-7.531,10.667-13.76c0-6.229-4.267-11.093-10.667-13.76v-31.147c6.4-2.667,10.667-7.531,10.667-13.76\n\t\t\ts-4.267-11.093-10.667-13.76v-23.573h10.667c5.888,0,10.667-4.779,10.667-10.667S507.223,170.587,501.335,170.587z\n\t\t\t M128.001,426.587H42.668v-42.667h85.333V426.587z M128.001,362.587H42.668v-42.667h85.333V362.587z M128.001,298.587H42.668\n\t\t\tv-42.667h85.333V298.587z M128.001,234.587H42.668v-85.333h85.333V234.587z M34.177,127.921l51.157-58.475l51.157,58.475H34.177z\n\t\t\t M224.001,341.254c-5.888,0-10.667-4.779-10.667-10.667s4.779-10.667,10.667-10.667s10.667,4.779,10.667,10.667\n\t\t\tS229.889,341.254,224.001,341.254z M330.668,319.921c-5.888,0-10.667-4.779-10.667-10.667s4.779-10.667,10.667-10.667\n\t\t\ts10.667,4.779,10.667,10.667S336.556,319.921,330.668,319.921z\"/>\n\t</g>\n</g></svg>" },
+ picnic: { title: "ピクニック・広場", svg: "<svg viewBox=\"0 0 512 512\" aria-hidden=\"true\"><g>\n\t<rect x=\"10.199\" y=\"228.645\" style=\"fill:#FF7731;\" width=\"491.602\" height=\"62.593\"/>\n\t<path style=\"fill:#FF7731;\" d=\"M482.422,291.243H29.578v85.334c0,66.844,54.187,121.031,121.031,121.031h210.784\n\t\tc66.843-0.001,121.03-54.188,121.03-121.031V291.243z\"/>\n</g>\n<rect x=\"361.613\" y=\"56.441\" style=\"fill:#BDCED4;\" width=\"50.068\" height=\"50.905\"/>\n<path style=\"fill:#FF2E48;\" d=\"M455.075,209.154c0-23.966-19.428-43.395-43.395-43.395v-58.416H361.61v58.416\n\tc-23.966,0-43.395,19.428-43.395,43.395v19.495h136.86V209.154z\"/>\n<rect x=\"224.607\" y=\"14.39\" style=\"fill:#FF7731;\" width=\"62.786\" height=\"276.847\"/>\n<rect x=\"58.135\" y=\"173.273\" style=\"fill:#BDCED4;\" width=\"138.709\" height=\"55.382\"/>\n<path d=\"M501.801,218.451h-36.526v-9.296c0-26.065-18.704-47.844-43.396-52.62v-49.191V56.438c0-5.633-4.567-10.199-10.199-10.199\n\th-50.071c-5.632,0-10.199,4.566-10.199,10.199v50.905v49.191c-24.69,4.776-43.394,26.555-43.394,52.62v9.296H297.59V14.391\n\tc0-5.633-4.567-10.199-10.199-10.199h-62.783c-5.632,0-10.199,4.566-10.199,10.199v204.06h-7.365v-45.177\n\tc0-5.633-4.567-10.199-10.199-10.199H58.135c-5.632,0-10.199,4.566-10.199,10.199v45.177H10.199C4.567,218.451,0,223.017,0,228.65\n\tv62.595c0,5.633,4.567,10.199,10.199,10.199h9.179v75.134c0,72.36,58.87,131.23,131.23,131.23h210.783\n\tc72.36,0,131.23-58.87,131.23-131.23v-75.134h9.179c5.632,0,10.199-4.566,10.199-10.199V228.65\n\tC512,223.017,507.433,218.451,501.801,218.451z M371.809,66.638h29.673v30.507h-29.673V66.638z M328.414,209.154\n\tc0-18.303,14.892-33.195,33.195-33.195c5.632,0,10.199-4.566,10.199-10.199v-48.217h29.673v48.217\n\tc0,5.633,4.567,10.199,10.199,10.199c18.305,0,33.196,14.892,33.196,33.195v9.296H328.414V209.154z M297.59,281.044v-42.196h194.011\n\tv42.196H297.59z M234.808,24.59h42.385v256.454h-42.385L234.808,24.59L234.808,24.59z M68.335,183.471h118.311v34.978H68.335\n\tV183.471z M20.398,281.044v-42.196H214.41v42.196H20.398z M472.223,301.443v75.134c0,61.113-49.719,110.832-110.832,110.832H150.609\n\tC89.496,487.408,39.777,437.69,39.777,376.577v-75.134H472.223z\"/>\n<path d=\"M386.55,343.599h12.239c5.632,0,10.199-4.566,10.199-10.199c0-5.633-4.567-10.199-10.199-10.199H386.55\n\tc-5.632,0-10.199,4.566-10.199,10.199C376.351,339.033,380.918,343.599,386.55,343.599z\"/>\n<path d=\"M62.215,333.4c0,5.633,4.567,10.199,10.199,10.199h269.259c5.632,0,10.199-4.566,10.199-10.199\n\tc0-5.633-4.567-10.199-10.199-10.199H72.414C66.782,323.201,62.215,327.767,62.215,333.4z\"/>\n<path d=\"M398.789,371.137H72.414c-5.632,0-10.199,4.566-10.199,10.199s4.567,10.199,10.199,10.199h326.375\n\tc5.632,0,10.199-4.566,10.199-10.199S404.421,371.137,398.789,371.137z\"/>\n<path d=\"M398.789,419.073H94.853c-5.632,0-10.199,4.566-10.199,10.199s4.567,10.199,10.199,10.199h303.936\n\tc5.632,0,10.199-4.566,10.199-10.199S404.421,419.073,398.789,419.073z\"/></svg>" },
+ ball: { title: "ボール遊び", svg: "<svg viewBox=\"0 0 64 64\" aria-hidden=\"true\" fill=\"currentColor\"><path d=\"M61.934 31.992c.021-.713.209-10.904-5.822-17.538c-.268-.593-1.539-2.983-5.641-5.904a41.959 41.959 0 0 0-5.775-3.763l-.008-.004C44.432 4.646 39.43 2 33.359 2c-.461 0-.917.027-1.368.058V2.05c-4.629-.101-9.227 1.09-11.998 2.341c-2.458 1.11-5.187 2.971-5.384 3.115C11.205 9.41 4.75 17.051 4.239 21.1c-2.063 2.637-3.787 14.482.004 21.697c2.658 10.027 12.664 15.045 13.46 15.43c.484.309 5.937 3.68 12.636 3.68c.281 0 1.98.094 2.586.094c7.241 0 17.971-5.104 20.217-9.102c6.171-4.514 9.37-16.147 8.792-20.907M17.758 47.055c-2.869-4.641-4.504-10.705-4.854-12.098c.908-1.361 5.387-7.965 7.939-9.952c1.445.266 7.479 1.374 13.17 2.404c.715 1.853 3.852 10.029 4.75 13.185c-.99 1.174-4.879 5.702-8.708 9.248c-4.065.019-10.979-2.326-12.297-2.787M53.824 14.58c-.012.45-.119 2.05-.885 3.887c-1.521-.777-5.344-2.441-10.584-2.722c-.793-1.171-3.777-5.254-8.49-8.086c.645-1.262 1.543-2.801 2.068-3.27c.17-.048.434-.092.836-.092c2.527 0 6.893 1.655 7.273 1.802c.403.213 8.251 4.439 9.782 8.481M11.773 34.012c-3.423-.584-5.458-1.648-6.066-2.008c-1.273-4.617-.248-9.607-.09-10.322c1.256-2.246 4.832-7.971 7.191-9.058c2.445-.499 5.494.121 6.736.424c-.117 1.615-.342 6.127.326 10.862c-2.706 2.178-6.989 8.447-8.097 10.102M31.685 3.53c.768.057 1.895.225 2.667.454c-.77 1.024-1.559 2.542-1.932 3.292c-1.57.257-7.533 1.397-12.211 4.43c-.943-.25-3.791-.917-6.488-.687c.668-1.293 1.666-2.249 1.773-2.347c.371-.266 7.513-5.263 16.191-5.155v.013m19.096 38.093c-1.17-.048-5.678-.305-10.621-1.466c-.947-3.302-4.074-11.444-4.789-13.296a556.586 556.586 0 0 1 6.928-9.654c5.688.312 9.682 2.387 10.455 2.82c3.295 5.299 4.018 10.711 4.117 11.615c-1.75 5.446-5.211 9.113-6.09 9.981M3.655 28.519c.084 1.266.287 2.599.654 3.917a11.738 11.738 0 0 0-.682 2.651a33.039 33.039 0 0 1 .028-6.568m9.644 23.359c1.508-1.453 3.367-2.867 4.088-3.401c1.63.574 8.324 2.837 12.591 2.837c.727.975 3.104 4.028 6.018 6.362c-1.814 1.775-4.434 2.613-4.897 2.752c-8.127.218-16.042-4.35-17.8-8.55m21.463 8.538c.922-.537 1.883-1.244 2.678-2.139c1.297-.179 6.863-1.137 11.893-4.832c.332.036.879.08 1.49.063c-3.018 2.957-10.382 6.26-16.061 6.908m15.424-8.376c1.807-4.708 1.73-8.258 1.641-9.392c.992-.972 4.396-4.599 6.285-10.113c1.018.17 1.68.429 1.994.574c.109.4.291 1.324.188 2.725c-.77 5.043-3.428 12.6-8.084 15.941c-.468.239-1.292.291-2.024.265\" fill=\"currentColor\"></path></svg>" },
+};
diff --git a/src/data/parks-rows.ts b/src/data/parks-rows.ts
new file mode 100644
index 0000000..39d7ae0
--- /dev/null
+++ b/src/data/parks-rows.ts
@@ -0,0 +1,141 @@
+import parksData from "@/data/kodaira-parks.json";
+import osmData from "@/data/parks-geojson";
+import nearbyData from "@/data/kodaira-nearby-parks.json";
+import facilitiesData from "@/data/kodaira-facilities.json";
+import nearbyFacilitiesData from "@/data/kodaira-nearby-facilities.json";
+
+export type Park = Record<string, string>;
+
+function nearbyCentroid(feature: any): [number, number] {
+ const g = feature.geometry;
+ if (g.type === "Point") return [g.coordinates[1], g.coordinates[0]];
+ const ring = g.type === "Polygon" ? g.coordinates[0] : g.coordinates[0][0];
+ if (!ring?.length) return [0, 0];
+ let lat = 0;
+ let lon = 0;
+ for (const [x, y] of ring) {
+ lon += x;
+ lat += y;
+ }
+ return [lat / ring.length, lon / ring.length];
+}
+
+function mapsQueryForNearby(name: string, city: string): string {
+ return name ? (city && !name.includes(city) ? `${city}${name}` : name) : "";
+}
+
+// 「小平市小川町2-1325」→「小川町」。公共施設の住所から町名を取り出す。
+function townFromAddress(address: string): string {
+ const match = /^小平市(.+?)(?:\d|$)/.exec(address || "");
+ return match ? match[1].trim() : "";
+}
+
+// 市境500m以内の市外公園。小平市の公園と同じ表に「市外」バッジ付きで並べる。
+const nearbyRows: Park[] = ((nearbyData as any).features ?? []).map((f: any) => {
+ const p = f.properties || {};
+ const [lat, lon] = nearbyCentroid(f);
+ const area = Math.round(Number(p.area_m2) || 0);
+ const name = String(p.name || "").trim();
+ const mapsQuery = name
+ ? mapsQueryForNearby(name, String(p.city || ""))
+ : `${lat},${lon}`;
+ return {
+ "公園名": name,
+ "住所": p.city ? `${p.city}(市外)` : "市外",
+ "町名": "市外",
+ "面積㎡": area ? String(area) : "",
+ "500㎡以上": "",
+ "種別": "市外",
+ "南西部指定管理": "",
+ "トイレ": "",
+ "水飲み場": "",
+ "ベンチ・椅子": "",
+ "テーブル": "",
+ "パーゴラ": "",
+ "東屋": "",
+ "防災用具": "",
+ "ボール遊び": "",
+ "遊具": "",
+ "駐車場": "",
+ "その他設備": "",
+ "緯度": String(lat),
+ "経度": String(lon),
+ "備考": `市外・小平市境から約${Math.round(Number(p.distance_m) || 0)}m${
+ f.geometry?.type === "Point" ? "・範囲未取得" : ""
+ }`,
+ "設置者": "市外",
+ "状態": "",
+ "地図キー": p.key || `${p.osm_type || ""}/${p.osm_id || ""}`,
+ "地図URL": `https://www.google.com/maps/search/?api=1&query=${encodeURIComponent(mapsQuery)}`,
+ };
+});
+
+// 市内・市外の公共施設を公園一覧と同じ行形式にする。
+function facilityRow(f: any, nearby: boolean): Park {
+ const name = String(f.name || "").trim();
+ const type = String(f.type || "");
+ const city = String(f.city || "").trim();
+ const address = String(f.address || city || (nearby ? "市外" : "")).trim();
+ const hours = f.hours ? `開館 ${f.hours}` : "";
+ const closed = f.closed ? `休館 ${f.closed}` : "";
+ const note = [type, hours, closed, f.note].filter(Boolean).join("。");
+ const mapsQuery = nearby ? mapsQueryForNearby(name, city) : `小平市${name}`;
+ const toilet = f.toilet === "○" ? "○" : "";
+ const water = f.water === "○" ? "○" : "";
+ return {
+ "公園名": name,
+ "住所": address,
+ "町名": nearby ? "市外" : townFromAddress(address),
+ "面積㎡": "",
+ "500㎡以上": "",
+ "種別": type,
+ "南西部指定管理": "",
+ "トイレ": toilet,
+ "水飲み場": "",
+ "給水": water,
+ "ベンチ・椅子": "",
+ "テーブル": "",
+ "パーゴラ": "",
+ "東屋": "",
+ "防災用具": "",
+ "ボール遊び": "",
+ "遊具": "",
+ "駐車場": "",
+ "その他設備": "",
+ "緯度": f.lat != null ? String(f.lat) : "",
+ "経度": f.lon != null ? String(f.lon) : "",
+ "備考": note,
+ "設置者": nearby ? "市外" : "小平市",
+ "状態": "",
+ "地図URL": `https://www.google.com/maps/search/?api=1&query=${encodeURIComponent(mapsQuery)}`,
+ "公式URL": String(f.source || ""),
+ "施設": "1",
+ };
+}
+
+const facilityRows: Park[] = [
+ ...(facilitiesData as any[]).map((f) => facilityRow(f, false)),
+ ...(nearbyFacilitiesData as any[]).map((f) => facilityRow(f, true)),
+];
+
+export const parks: Park[] = [
+ ...(parksData as Park[]),
+ ...nearbyRows,
+ ...facilityRows,
+];
+
+export const total = parks.length;
+
+export const towns = [...new Set(parks.map((p) => p["町名"]).filter(Boolean))].sort(
+ (a, b) => a.localeCompare(b, "ja"),
+);
+
+// OpenStreetMapにポリゴンがあり、地図から位置を表示できる公園名。
+export const mappedNames = new Set<string>([
+ ...(osmData as any).features
+ .map((f: any) => f.properties?.our_name)
+ .filter(Boolean),
+ ...((nearbyData as any).features ?? [])
+ .map((f: any) => String(f.properties?.name || "").trim())
+ .filter(Boolean),
+]);
diff --git a/src/styles/custom.css b/src/styles/custom.css
index 1ea4aa7..ba1f7ed 100644
--- a/src/styles/custom.css
+++ b/src/styles/custom.css
@@ -173,6 +173,68 @@
box-shadow: none;
}
+/* 公園ページの折りたたみ(説明・凡例) */
+.sl-markdown-content details.page-help,
+.sl-markdown-content details.park-map-help {
+ margin: 0.75rem 0;
+ border: 1px solid var(--sl-color-gray-5);
+ border-radius: 10px;
+ background: var(--sl-color-gray-6);
+ overflow: hidden;
+}
+.sl-markdown-content details.page-help > summary,
+.sl-markdown-content details.park-map-help > summary {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ gap: 0.5rem;
+ padding: 0.65rem 0.9rem;
+ background: transparent;
+ color: var(--sl-color-text);
+ font-size: 0.92rem;
+ font-weight: 600;
+ list-style: none;
+}
+.sl-markdown-content details.page-help > summary::-webkit-details-marker,
+.sl-markdown-content details.park-map-help > summary::-webkit-details-marker {
+ display: none;
+}
+.sl-markdown-content details.page-help > summary::after,
+.sl-markdown-content details.park-map-help > summary::after {
+ content: "▾";
+ flex: none;
+ color: var(--sl-color-gray-3);
+ transition: transform 0.15s ease;
+}
+.sl-markdown-content details.page-help[open] > summary::after,
+.sl-markdown-content details.park-map-help[open] > summary::after {
+ transform: rotate(180deg);
+}
+.sl-markdown-content details.page-help > summary:hover,
+.sl-markdown-content details.park-map-help > summary:hover {
+ background: var(--sl-color-gray-5);
+}
+.sl-markdown-content details.page-help[open] > summary,
+.sl-markdown-content details.park-map-help[open] > summary {
+ border-bottom: 1px solid var(--sl-color-gray-5);
+}
+.sl-markdown-content details.page-help > p,
+.sl-markdown-content details.page-help > ul,
+.sl-markdown-content details.page-help > ol,
+.sl-markdown-content details.park-map-help > p {
+ margin-left: 0.9rem;
+ margin-right: 0.9rem;
+}
+.sl-markdown-content details.page-help > p:first-of-type,
+.sl-markdown-content details.park-map-help > p:first-of-type {
+ margin-top: 0.65rem;
+}
+.sl-markdown-content details.page-help > p:last-child,
+.sl-markdown-content details.page-help > ul:last-child,
+.sl-markdown-content details.park-map-help > p:last-child {
+ margin-bottom: 0.75rem;
+}
+
/* ── アーカイブの表(保存日・更新日の列) ── */
.archive-table table th:nth-child(2),
.archive-table table td:nth-child(2),