aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/components/ParkMap.astro41
-rw-r--r--src/components/ParksTable.astro8
-rw-r--r--src/data/parks-geojson.ts19
3 files changed, 62 insertions, 6 deletions
diff --git a/src/components/ParkMap.astro b/src/components/ParkMap.astro
index 7ca85ab..ac85c0e 100644
--- a/src/components/ParkMap.astro
+++ b/src/components/ParkMap.astro
@@ -629,7 +629,21 @@
lyr._parkName = ourName;
lyr._osmName = name;
allLayers.push(lyr);
- if (ourName) layersByName.set(ourName, lyr);
+ if (ourName) {
+ const existing = layersByName.get(ourName);
+ if (!existing) {
+ layersByName.set(ourName, lyr);
+ } else if (
+ typeof existing.getLayers === "function" &&
+ typeof existing.addLayer === "function"
+ ) {
+ existing.addLayer(lyr);
+ } else {
+ const group = L.featureGroup([existing, lyr]);
+ group._osmName = existing._osmName;
+ layersByName.set(ourName, group);
+ }
+ }
if (ourName) {
lyr.on("add", () => {
@@ -760,6 +774,25 @@
addFacilities(nearbyFacilities as any[], true);
publicFacilityLayer.addTo(map);
+ // 道路で分かれた公園など、同じ公園に複数のポリゴンがある場合は
+ // いちばん大きいポリゴンの中心にアイコンを置く。
+ const centerOfLayer = (lyr: any) => {
+ if (lyr && typeof lyr.getLayers === "function") {
+ let best: any = null;
+ let bestArea = -1;
+ for (const child of lyr.getLayers()) {
+ const b = child.getBounds();
+ const area = (b.getNorth() - b.getSouth()) * (b.getEast() - b.getWest());
+ if (area > bestArea) {
+ bestArea = area;
+ best = child;
+ }
+ }
+ if (best) return best.getBounds().getCenter();
+ }
+ return lyr.getBounds().getCenter();
+ };
+
// 拡大時だけ表示する設備アイコン(トイレ・水飲み場)
// 一覧と一致した公園のポリゴン内にだけ表示する。
const facilityLayer = L.layerGroup();
@@ -778,7 +811,7 @@
);
}
const clock = (p["時計"] || "").trim();
- if (clock === "○" || clock === "あり" || clock === "有") {
+ if (clock === "○" || clock === "あり" || clock === "有" || clock === "1") {
icons.push(
'<span class="park-fac park-fac-clock" title="時計あり" aria-label="時計あり">⏰</span>',
);
@@ -795,7 +828,7 @@
);
}
if (!icons.length) return;
- const center = lyr.getBounds().getCenter();
+ const center = centerOfLayer(lyr);
L.marker([center.lat, center.lng], {
icon: L.divIcon({
className: "park-fac-markers",
@@ -854,7 +887,7 @@
);
}
if (!icons.length) return;
- const center = lyr.getBounds().getCenter();
+ const center = centerOfLayer(lyr);
L.marker([center.lat, center.lng], {
icon: L.divIcon({
className: "park-play-markers",
diff --git a/src/components/ParksTable.astro b/src/components/ParksTable.astro
index f0864d6..17841cc 100644
--- a/src/components/ParksTable.astro
+++ b/src/components/ParksTable.astro
@@ -123,13 +123,15 @@ function facTokens(p: Park): string {
const ball = p["ボール遊び"];
if (ball && ball !== "禁止") tokens.push("ball");
const clock = (p["時計"] || "").trim();
- if (clock === "○" || clock === "あり" || clock === "有") tokens.push("clock");
+ if (clock === "○" || clock === "あり" || clock === "有" || clock === "1") tokens.push("clock");
if (p["南西部指定管理"]) tokens.push("cm");
// ピクニック広場・芝生広場・テーブルのある公園。
const picnicText = `${p["公園名"] || ""} ${p["種別"] || ""} ${p["その他設備"] || ""} ${p["備考"] || ""}`;
if (
(p["テーブル"] || "").trim() ||
p["種別"] === "広場" ||
+ p["草地広場"] ||
+ p["多目的広場"] ||
picnicText.includes("芝生") ||
picnicText.includes("ピクニック") ||
picnicText.includes("広場")
@@ -145,6 +147,8 @@ const DETAIL_FIELDS: { key: string; icon: string }[] = [
{ key: "ベンチ・椅子", icon: "🪑" },
{ key: "テーブル", icon: "🍽" },
{ key: "シェルター等", icon: "⛱" },
+ { key: "草地広場", icon: "🌿" },
+ { key: "多目的広場", icon: "🏟" },
{ key: "防災用具", icon: "🧯" },
{ key: "遊具", icon: "🎠" },
{ key: "時計", icon: "⏰" },
@@ -211,6 +215,8 @@ function searchIndex(p: Park): string {
p["トイレ"],
p["水飲み場"],
p["給水"],
+ p["草地広場"] ? "草地広場" : "",
+ p["多目的広場"] ? "多目的広場" : "",
p["ボール遊び"],
...DETAIL_FIELDS.map((f) => p[f.key]),
]
diff --git a/src/data/parks-geojson.ts b/src/data/parks-geojson.ts
index e12d297..9fd9d4f 100644
--- a/src/data/parks-geojson.ts
+++ b/src/data/parks-geojson.ts
@@ -20,6 +20,23 @@ function isHiddenUnlisted(props: any): boolean {
const osmFeatures = ((osm as any).features ?? []).filter(
(f: any) => !isHiddenUnlisted(f.properties),
);
-const features = [...osmFeatures, ...((manual as any).features ?? [])];
+const manualFeatures = (manual as any).features ?? [];
+
+// 手入力ポリゴンでOSM側の形を置き換える公園(例: 道路で分かれた公園)。
+// QGISの属性 override=true、または import-manual-parks.py の --override-name で付く。
+const overrideNames = new Set(
+ manualFeatures
+ .filter((f: any) => {
+ const value = f?.properties?.override;
+ return value === true || value === 1 || value === "true" || value === "1";
+ })
+ .map((f: any) => f?.properties?.our_name)
+ .filter(Boolean),
+);
+
+const features = [
+ ...osmFeatures.filter((f: any) => !overrideNames.has(f.properties?.our_name)),
+ ...manualFeatures,
+];
export default { type: "FeatureCollection", features };