satupeta-main/shared/components/map-legend.tsx

72 lines
2.0 KiB
TypeScript
Raw Normal View History

2026-01-27 02:31:12 +00:00
import Image from "next/image";
import { parseWmsUrl } from "../utils/wms";
export function MapLegend({
parsed,
width = 600,
}: {
parsed: ReturnType<typeof parseWmsUrl>;
width: number;
}) {
if (!parsed?.baseUrl || !parsed?.params?.layers) return null;
const layers = String(parsed.params.layers)
.split(",")
.map((l) => l.trim())
.filter(Boolean);
const styles = parsed.params.styles
? String(parsed.params.styles)
.split(",")
.map((s) => s.trim())
: [];
return (
<div className="pointer-events-none absolute left-3 bottom-3 z-[1001]">
<div className="pointer-events-auto bg-white/90 backdrop-blur rounded-md border shadow p-2 max-w-[min(90vw,360px)]">
{layers.map((layer, i) => {
const style = styles[i];
const url = buildLegendUrl(parsed, layer, style);
return (
<div key={layer} className="mb-2 last:mb-0">
<div style={{ maxWidth: width }}>
<Image
src={url}
alt={`Legend ${layer}`}
width={0}
height={0}
sizes={`${width}px`}
style={{ width: "100%", height: "auto" }}
className="object-cover"
/>
</div>
</div>
);
})}
</div>
</div>
);
}
// local function
function buildLegendUrl(
parsed: ReturnType<typeof parseWmsUrl> | null | undefined,
layer: string,
style?: string
) {
if (!parsed?.baseUrl) {
return "";
}
const u = new URL(parsed.baseUrl);
u.searchParams.set("SERVICE", "WMS");
u.searchParams.set("REQUEST", "GetLegendGraphic");
u.searchParams.set("VERSION", parsed.params.version || "1.1.1");
u.searchParams.set("FORMAT", "image/png");
u.searchParams.set("TRANSPARENT", "true");
u.searchParams.set("LAYER", layer);
if (style) u.searchParams.set("STYLE", style); // if use specific style
u.searchParams.set("SLD_VERSION", "1.1.0");
return u.toString();
}