폴리곤 생성시 질문

안녕하세요 리액트로 카카오맵에 시/도 단위로 폴리곤을 만드려 합니다.

폴리곤이 다 로딩된 후 다시 한번 지도를 그리면 축소/확대할때 축소/확대 전 지도모양이 남아있는데 어떻게 해결해야하나요?

또한 렌더링할때 {areas&& } 대신 {isloaded&& }을 사용하면 CORS에러가 발생하는데 해결법이 있을까요?

import "../styles/test.scss";
import React, { useEffect, useState } from "react";
import sido from "../data/sido.json";
const { kakao } = window;

function Map() {
  const [areas, setAreas] = useState([]);
  const [isloaded, setIsloaded] = useState(false);

  useEffect(() => {
    const result = pushData();
    setAreas(areas.concat(result));
    setMap();
  }, [isloaded]);
  useEffect(() => {
    console.log(areas);
  }, []);

  function pushData() {
    let newData = {
      name: sido.features[0].properties.CTP_KOR_NM,
      path: [],
    };
    sido.features[0].geometry.coordinates.map((arr) =>
      arr.map((data) =>
        newData.path.push(new kakao.maps.LatLng(data[1], data[0]))
      )
    );

    return newData;
  }

  function setMap() {
    const container = document.getElementById("map");
    const options = {
      center: new kakao.maps.LatLng(37.504894, 127.0456489),
      level: 5,
    };
    const map = new kakao.maps.Map(container, options),
      customOverlay = new kakao.maps.CustomOverlay({}),
      infowindow = new kakao.maps.InfoWindow({ removable: true });

    function displayArea(area) {
      // 다각형을 생성합니다
      let polygon = new kakao.maps.Polygon({
        map: map, // 다각형을 표시할 지도 객체
        path: area.path,
        strokeWeight: 2,
        strokeColor: "#004c80",
        strokeOpacity: 0.8,
        fillColor: "#fff",
        fillOpacity: 0.7,
      });

      // 다각형에 mouseover 이벤트를 등록하고 이벤트가 발생하면 폴리곤의 채움색을 변경합니다
      // 지역명을 표시하는 커스텀오버레이를 지도위에 표시합니다
      polygon.addListener("mouseover", function (mouseEvent) {
        polygon.setOptions({ fillColor: "#09f" });

        customOverlay.setContent('<div class="area">' + area.name + "</div>");

        customOverlay.setPosition(mouseEvent.latLng);
        customOverlay.setMap(map);
      });

      // 다각형에 mousemove 이벤트를 등록하고 이벤트가 발생하면 커스텀 오버레이의 위치를 변경합니다
      polygon.addListener("mousemove", function (mouseEvent) {
        customOverlay.setPosition(mouseEvent.latLng);
      });

      // 다각형에 mouseout 이벤트를 등록하고 이벤트가 발생하면 폴리곤의 채움색을 원래색으로 변경합니다
      // 커스텀 오버레이를 지도에서 제거합니다
      polygon.addListener("mouseout", function () {
        polygon.setOptions({ fillColor: "#fff" });
        customOverlay.setMap(null);
      });

      // 다각형에 click 이벤트를 등록하고 이벤트가 발생하면 다각형의 이름과 면적을 인포윈도우에 표시합니다
      polygon.addListener("click", function (mouseEvent) {
        let content = `<div class="info">
          <div class="title">
          area.name
          </div></div>`;

        infowindow.setContent(content);
        infowindow.setPosition(mouseEvent.latLng);
        infowindow.setMap(map);
      });
    }
    areas.map((area) => displayArea(area));
    setIsloaded(true);
  }

  return (
    <>
      {areas && (
        <div id="map" style={{ width: "100%", height: "70vh" }}></div>
      )}
    </>
  );
}

export default Map;

폴리곤이 로드될 때 지도를 다시 그리는 방법이 아닌
로드된 폴리곤 정보로 폴리곤 객체를 생성해서 지도에 표출해주세요.
지도 객체는 1개만 생성해서 사용해주세요.

그리고 두 상태값 중 하나를 비교 연산자에 넣어도 에러가 나지 않는데요.
에러 메세지와 로직 확인해서 오류를 해결해주세요.

그럼 상태로 관리하는게 아닌 미리 예제의 areas처럼 만들어 놓은 데이터를 이용해야하나요?

상태 관리로 폴리곤 정보를 관리해도 됩니다.
지도를 여러 번 생성하는 것이 아닌 최초 한 번 생성하고
그 위에 폴리곤 정보를 받아 표출하는 방식으로 구현해주세요.

아래 예제도 함께 참고해주세요.
https://codesandbox.io/s/gifted-wescoff-77nwu

감사합니다 폴리곤 생성때는 new kakao.maps.LatLng(값1, 값2) 이렇게 와야하는데 올려주신 마커예제처럼 좌표만 받아서 이부분을 만드는 예제로 혹시 만들어주실수 있으신가요?

예제를 조금 변형해서 첨부 코드의 pushData 로직으로 polygon path를 설정하고 지도에 표시하는 방법도 있습니다.
아래는 첨부 코드를 조금 수정한 코드입니다.
참고만 해주세요.

export default function KakaoMap() {
  const [areas, setAreas] = useState([]);
  const [isloaded, setIsloaded] = useState(false);
  const [kakaoMap, setKakaoMap] = useState(null);
  const container = useRef();

  useEffect(() => {
    const script = document.createElement("script");
    script.src = "https://dapi.kakao.com/v2/maps/sdk.js?appkey=Javascript 앱 키를 사용해주세요.&autoload=false";
    document.head.appendChild(script);

    script.onload = () => {
        kakao.maps.load(() => {
            setMap();
            setPolygonPath();
        });
    };
  }, []);

  function setPolygonPath() {
      const positions = data.positions.map((position, i) => {
          return new kakao.maps.LatLng(position.lat, position.lng);
        });

        setAreas(positions);
        setIsloaded(true);
  }

  function setMap() {
    const options = {
        center: new kakao.maps.LatLng(33.450701, 126.570667),
        level: 3
    };

    const map = new kakao.maps.Map(container.current, options);
    setKakaoMap(map);
  }


  useEffect(() => {
      if(isloaded) {
          // 필요한 경우 폴리곤을 state에 담아 관리합니다.
          const polygon = new kakao.maps.Polygon({
              map: kakaoMap,
              path: areas
          });
      }

  }, [isloaded])


return (
    <>
      {(
        <div id="map" ref={container} style={{ width: "100%", height: "70vh" }}></div>
      )}
    </>
  );
1개의 좋아요

감사합니다 저는 화살표함수에서 () => new kakao.maps.LatLng( , ) 이렇게만 하면되는줄 알았는데 return 을 붙이고 값을 할당해줘야했더감사합니다 저는 화살표함수에서 () => new kakao.maps.LatLng( , ) 이렇게만 하면되는줄 알았는데 return 을 붙여야 되는거였네요 도와주셔서 감사합니다

중괄호를 했을 경우는 return을 해주고 괄호인 경우는 return문을 작성하지 않아도 됩니다.
말씀처럼 아래와 같이 사용할 수 있습니다.

const positions = data.positions.map((position) => new kakao.maps.LatLng(position.lat, position.lng));

화살표 함수 mdn 문서도 참고해주세요.
https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Functions/Arrow_functions

엇 그러네요 제가 변환한 값을 할당해주지 않아서 그랬던것 같습니다. kakaomap 변수는 map상태를 관리하기 위해 사용하는거죠? 그리고 혹시 infowindow랑 customoverlay상태도 관리가 가능한가요?

어떤 상태를 말씀하시는 것인지는 정확히 저희가 알 수 없으며
상황에 따라 무엇을 상태값으로 둘지, 어떻게 코드를 작성해야 하는지도 달라집니다.
이는 본인이 판단하셔야 하며 저희가 제공해 드린 샘플로 충분히 가능성을 짐작하실 수 있다고 봅니다.
그래야만 이 후에 기능을 확장해 나가시는데 수월하실 거에요.

1개의 좋아요