import { geoJsonString } from "@/lib/geo-json-string"; import { NezhaServer } from "@/types/nezha-api"; import { useState } from "react"; import { useTranslation } from "react-i18next"; import { AnimatePresence, m } from "framer-motion"; import { geoEquirectangular, geoPath } from "d3-geo"; import { countryCoordinates } from "@/lib/geo-limit"; export default function GlobalMap({ serverList, }: { serverList: NezhaServer[]; }) { const { t } = useTranslation(); const countryList: string[] = []; const serverCounts: { [key: string]: number } = {}; console.log(serverList); serverList.forEach((server) => { if (server.country_code) { const countryCode = server.country_code.toUpperCase(); if (!countryList.includes(countryCode)) { countryList.push(countryCode); } serverCounts[countryCode] = (serverCounts[countryCode] || 0) + 1; } }); const width = 900; const height = 500; const geoJson = JSON.parse(geoJsonString); const filteredFeatures = geoJson.features.filter( (feature: { properties: { iso_a3_eh: string } }) => feature.properties.iso_a3_eh !== "", ); return (

{t("map.Distributions")} {countryList.length} {t("map.Regions")}

); } interface InteractiveMapProps { countries: string[]; serverCounts: { [key: string]: number }; width: number; height: number; filteredFeatures: { type: "Feature"; properties: { iso_a2_eh: string; [key: string]: string; }; geometry: never; }[]; } function InteractiveMap({ countries, serverCounts, width, height, filteredFeatures, }: InteractiveMapProps) { const { t } = useTranslation(); const [tooltipData, setTooltipData] = useState<{ centroid: [number, number]; country: string; count: number; } | null>(null); const projection = geoEquirectangular() .scale(140) .translate([width / 2, height / 2]) .rotate([-12, 0, 0]); const path = geoPath().projection(projection); return (
{filteredFeatures.map((feature, index) => { const isHighlighted = countries.includes( feature.properties.iso_a2_eh, ); if (isHighlighted) { console.log(feature.properties.iso_a2_eh); } const serverCount = serverCounts[feature.properties.iso_a2_eh] || 0; return ( { if (isHighlighted && path.centroid(feature)) { setTooltipData({ centroid: path.centroid(feature), country: feature.properties.name, count: serverCount, }); } }} onMouseLeave={() => setTooltipData(null)} /> ); })} {/* 渲染不在 filteredFeatures 中的国家标记点 */} {countries.map((countryCode) => { // 检查该国家是否已经在 filteredFeatures 中 const isInFilteredFeatures = filteredFeatures.some( (feature) => feature.properties.iso_a2_eh === countryCode, ); // 如果已经在 filteredFeatures 中,跳过 if (isInFilteredFeatures) return null; // 获取国家的经纬度 const coords = countryCoordinates[countryCode]; if (!coords) return null; // 使用投影函数将经纬度转换为 SVG 坐标 const [x, y] = projection([coords.lng, coords.lat]) || [0, 0]; const serverCount = serverCounts[countryCode] || 0; return ( { setTooltipData({ centroid: [x, y], country: coords.name, count: serverCount, }); }} onMouseLeave={() => setTooltipData(null)} className="cursor-pointer" > ); })} {tooltipData && (

{tooltipData.country === "China" ? "Mainland China" : tooltipData.country}

{tooltipData.count} {t("map.Servers")}

)}
); }