polling 및 마커 종류 설정 추가

This commit is contained in:
dohyeons
2025-11-12 17:21:08 +09:00
parent 68184ac49f
commit 54b7cae218
5 changed files with 232 additions and 89 deletions

View File

@@ -65,10 +65,6 @@ interface PolygonData {
}
export default function MapTestWidgetV2({ element }: MapTestWidgetV2Props) {
console.log("🗺️ MapTestWidgetV2 컴포넌트 마운트/렌더링");
console.log("📦 element:", element);
console.log("📊 dataSources:", element?.dataSources);
const [markers, setMarkers] = useState<MarkerData[]>([]);
const [prevMarkers, setPrevMarkers] = useState<MarkerData[]>([]); // 이전 마커 위치 저장
const [polygons, setPolygons] = useState<PolygonData[]>([]);
@@ -911,31 +907,29 @@ export default function MapTestWidgetV2({ element }: MapTestWidgetV2Props) {
// 초기 로드 및 자동 새로고침 (마커 데이터만 polling)
useEffect(() => {
console.log("🔄 지도 위젯 초기화 useEffect 실행됨!");
console.log("📊 dataSources 상태:", dataSources);
if (!dataSources || dataSources.length === 0) {
console.log("⚠️ dataSources가 없거나 비어있음 - polling 시작 안함");
setMarkers([]);
setPolygons([]);
return;
}
// 즉시 첫 로드 (마커 데이터)
console.log("📡 초기 마커 데이터 로드");
loadMultipleDataSources();
// 5초마다 마커 데이터만 자동 새로고침 (지도 타일은 안 건드림)
const refreshInterval = 5;
console.log(`⏱️ 마커 polling 시작: ${refreshInterval}초마다`);
// 첫 번째 데이터 소스의 새로고침 간격 사용 (초)
const firstDataSource = dataSources[0];
const refreshInterval = firstDataSource?.refreshInterval ?? 5;
// 0이면 자동 새로고침 비활성화
if (refreshInterval === 0) {
return;
}
const intervalId = setInterval(() => {
console.log("🔄 마커 자동 새로고침 실행");
loadMultipleDataSources();
}, refreshInterval * 1000);
return () => {
console.log("⏹️ 마커 polling 정리");
clearInterval(intervalId);
};
// eslint-disable-next-line react-hooks/exhaustive-deps
@@ -1124,59 +1118,103 @@ export default function MapTestWidgetV2({ element }: MapTestWidgetV2Props) {
</Polygon>
))}
{/* 마커 렌더링 (화살표 모양) */}
{/* 마커 렌더링 */}
{markers.map((marker) => {
// 화살표 아이콘 생성 (진행 방향으로 회전)
let arrowIcon: any;
// 첫 번째 데이터 소스의 마커 종류 가져오기
const firstDataSource = dataSources?.[0];
const markerType = firstDataSource?.markerType || "circle";
let markerIcon: any;
if (typeof window !== "undefined") {
const L = require("leaflet");
const heading = marker.heading || 0;
arrowIcon = L.divIcon({
className: "custom-arrow-marker",
html: `
<div style="
width: 40px;
height: 40px;
display: flex;
align-items: center;
justify-content: center;
transform: translate(-50%, -50%) rotate(${heading}deg);
filter: drop-shadow(0 2px 4px rgba(0,0,0,0.3));
">
<svg width="40" height="40" viewBox="0 0 40 40" xmlns="http://www.w3.org/2000/svg">
<!-- 화살표 몸통 -->
<polygon
points="20,5 25,15 23,15 23,25 17,25 17,15 15,15"
fill="${marker.color || "#3b82f6"}"
stroke="white"
stroke-width="1.5"
/>
<!-- 화살촉 -->
<polygon
points="20,2 28,12 12,12"
fill="${marker.color || "#3b82f6"}"
stroke="white"
stroke-width="1.5"
/>
<!-- 중심점 -->
<circle
cx="20"
cy="30"
r="3"
fill="white"
stroke="${marker.color || "#3b82f6"}"
stroke-width="1.5"
/>
</svg>
</div>
`,
iconSize: [40, 40],
iconAnchor: [20, 20],
});
if (markerType === "arrow") {
// 화살표 마커
markerIcon = L.divIcon({
className: "custom-arrow-marker",
html: `
<div style="
width: 40px;
height: 40px;
display: flex;
align-items: center;
justify-content: center;
transform: translate(-50%, -50%) rotate(${heading}deg);
filter: drop-shadow(0 2px 4px rgba(0,0,0,0.3));
">
<svg width="40" height="40" viewBox="0 0 40 40" xmlns="http://www.w3.org/2000/svg">
<!-- 화살표 몸통 -->
<polygon
points="20,5 25,15 23,15 23,25 17,25 17,15 15,15"
fill="${marker.color || "#3b82f6"}"
stroke="white"
stroke-width="1.5"
/>
<!-- 화살촉 -->
<polygon
points="20,2 28,12 12,12"
fill="${marker.color || "#3b82f6"}"
stroke="white"
stroke-width="1.5"
/>
<!-- 중심점 -->
<circle
cx="20"
cy="30"
r="3"
fill="white"
stroke="${marker.color || "#3b82f6"}"
stroke-width="1.5"
/>
</svg>
</div>
`,
iconSize: [40, 40],
iconAnchor: [20, 20],
});
} else {
// 동그라미 마커 (기본)
markerIcon = L.divIcon({
className: "custom-circle-marker",
html: `
<div style="
width: 32px;
height: 32px;
display: flex;
align-items: center;
justify-content: center;
transform: translate(-50%, -50%);
filter: drop-shadow(0 2px 4px rgba(0,0,0,0.3));
">
<svg width="32" height="32" viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg">
<!-- 외부 원 -->
<circle
cx="16"
cy="16"
r="14"
fill="${marker.color || "#3b82f6"}"
stroke="white"
stroke-width="2"
/>
<!-- 내부 점 -->
<circle
cx="16"
cy="16"
r="6"
fill="white"
/>
</svg>
</div>
`,
iconSize: [32, 32],
iconAnchor: [16, 16],
});
}
}
return (
<Marker key={marker.id} position={[marker.lat, marker.lng]} icon={arrowIcon}>
<Marker key={marker.id} position={[marker.lat, marker.lng]} icon={markerIcon}>
<Popup maxWidth={350}>
<div className="max-w-[350px] min-w-[250px]">
{/* 제목 */}