![](/onboardingBag.png)
+
![]()
();
+ const [map, setMap] = useState
(null);
+ const [markers, setMarkers] = useState([]);
+
+ function addPin(data: SearchItemType[]) {
+ const currentMarkers: any[] = [];
+
+ data.map((data, i) => {
+ let image;
+ let imageSize;
+ let imageOption;
+ if (i === currentpin) {
+ image =
+ data.category === "숙소"
+ ? bigHomeMarker
+ : data.category === "맛집"
+ ? bigForkMarker
+ : bigFlagMarker;
+ imageSize = new window.kakao.maps.Size(44, 52);
+ imageOption = { offset: new window.kakao.maps.Point(0, 0) };
+ } else {
+ image =
+ data.category === "숙소"
+ ? homeMarker
+ : data.category === "맛집"
+ ? forkMarker
+ : flagMarker;
+ imageSize = new window.kakao.maps.Size(32, 32);
+ imageOption = { offset: new window.kakao.maps.Point(-6, -10) };
+ }
+
+ const markerImage = new window.kakao.maps.MarkerImage(
+ image,
+ imageSize,
+ imageOption,
+ );
+ const marker = new window.kakao.maps.Marker({
+ position: new window.kakao.maps.LatLng(
+ data.location.latitude,
+ data.location.longtitude,
+ ),
+ image: markerImage,
+ });
+ if (i == currentpin) {
+ marker.setZIndex(10);
+ }
+ marker.setMap(map);
+ currentMarkers.push(marker);
+ });
+ setMarkers([...currentMarkers]);
+ }
+ function removePin(marker: any[]) {
+ marker.map((marker) => {
+ marker.setMap(null);
+ });
+ return true;
+ }
+
+ // 컴포넌트 마운트, 카테고리 전환 시 새로운 맵 생성
+ useEffect(() => {
+ const container = document.getElementById("map");
+
+ // React.StrictMode로 인해 map이 두 번 중첩되어 겹치는 현상 방지
+ if (container) {
+ while (container.firstChild) {
+ container.removeChild(container.firstChild);
+ }
+ }
+
+ const options = {
+ center: new window.kakao.maps.LatLng(33.450701, 126.570667),
+ level: 3,
+ };
+ setMap(new window.kakao.maps.Map(container, options));
+ }, [data]);
+
+ // 맵 생성 시 현재 데이터 좌표들의 바운드를 만들어 중심점 생성
+ useEffect(() => {
+ if (map) {
+ const bounds = new window.kakao.maps.LatLngBounds();
+ addPin(data);
+ data.map((data) => {
+ bounds.extend(
+ new window.kakao.maps.LatLng(
+ data.location.latitude,
+ data.location.longtitude,
+ ),
+ );
+ });
+ map.setBounds(bounds);
+ }
+ }, [map]);
+
+ // 현재 화면에 보이는 아이템의 아이콘 변경
+ useEffect(() => {
+ if (map) {
+ removePin(markers);
+ addPin(data);
+ }
+ }, [currentpin]);
+
return (
);
}
diff --git a/src/components/SearchFromHome/SearchList/Map/MapItems/MapItem/MapItem.tsx b/src/components/SearchFromHome/SearchList/Map/MapItems/MapItem/MapItem.tsx
index d795d614..0b4bf3c6 100644
--- a/src/components/SearchFromHome/SearchList/Map/MapItems/MapItem/MapItem.tsx
+++ b/src/components/SearchFromHome/SearchList/Map/MapItems/MapItem/MapItem.tsx
@@ -18,7 +18,7 @@ function MapItem({ data, categoryChange }: PropsType) {
{data.title}
- {data.category}·{data.location}
+ {data.category}·{data.location.address}
diff --git a/src/components/SearchFromHome/SearchList/Map/MapItems/MapItems.tsx b/src/components/SearchFromHome/SearchList/Map/MapItems/MapItems.tsx
index 1ea4ec5a..f12d6136 100644
--- a/src/components/SearchFromHome/SearchList/Map/MapItems/MapItems.tsx
+++ b/src/components/SearchFromHome/SearchList/Map/MapItems/MapItems.tsx
@@ -13,11 +13,41 @@ import { SearchItemType } from "@/types/home";
interface PropsType {
data: SearchItemType[];
categoryChange: boolean;
+ setCurrentPin: React.Dispatch
>;
}
-function MapItems({ data, categoryChange }: PropsType) {
+function MapItems({ data, categoryChange, setCurrentPin }: PropsType) {
const [slideLocation, setSlideLocation] = useState(0);
const [componentRef, size] = useComponentSize();
+ const [throttle, setThrottle] = useState(false);
+
+ function setCurrentIndex() {
+ const criterion = document.querySelector("#map_slide_container");
+ const elements = document.querySelectorAll("#map_slide");
+ const childrenArray = Array.from(elements[0].children);
+
+ for (const item of childrenArray) {
+ const currentLeft =
+ criterion &&
+ item.getBoundingClientRect().x - criterion.getBoundingClientRect().x;
+ if (currentLeft) {
+ if (0 < currentLeft && currentLeft < 196) {
+ const index = childrenArray.indexOf(item);
+ setCurrentPin(index);
+ }
+ }
+ }
+ }
+
+ const handleScroll = () => {
+ if (throttle) return;
+ if (!throttle) {
+ setThrottle(true);
+ setTimeout(async () => {
+ setThrottle(false);
+ }, 300);
+ }
+ };
useEffect(() => {
if (size.width < 449) {
@@ -27,8 +57,20 @@ function MapItems({ data, categoryChange }: PropsType) {
}
}, [data, size, componentRef]);
+ useEffect(() => {
+ setTimeout(() => {
+ setCurrentIndex();
+ }, 600);
+ }, [slideLocation]);
+
+ useEffect(() => {
+ if (throttle) {
+ setCurrentIndex();
+ }
+ }, [throttle]);
+
return (
-
+
{data && (
{data &&
data.map((data, i) => (
diff --git a/src/components/SearchFromHome/SearchList/MapButton/MapButton.tsx b/src/components/SearchFromHome/SearchList/MapButton/MapButton.tsx
index 73539784..2760d1cf 100644
--- a/src/components/SearchFromHome/SearchList/MapButton/MapButton.tsx
+++ b/src/components/SearchFromHome/SearchList/MapButton/MapButton.tsx
@@ -4,12 +4,12 @@ import styles from "./MapButton.module.scss";
function MapButton() {
return (
-