naver map

yyeonggg·2023년 2월 3일
0
const renderListingMarkers = useCallback(
    async (m: naver.maps.Map) => {
      if (listOpen) return;

      const response = await searchListing(m, getFilterFromSearchParams());
      setTotalListingCount(response?.total_result_count || 0);

      const markers: ListingMarkers = {};
      response?.results?.forEach((item) => {
        const key = `lat:${item.lat}lng:${item.long}`;
        markers[key] = item;
      });

      setListingMarkers(markers);
    },
    [listOpen],
  );

Object.entries 사용 (객체 -> 배열 메서드 사용)

{Object.entries(listingMarkers).map(([key, marker]) => {
          return (
            <CustomOverlay
              key={key}
              position={{
                lat: marker.lat,
                lng: marker.long,
              }}
            >
              {marker.bubjungdong_name ? (
                <NamedListingMarker
                  onClick={() => onClickListingMarker(marker)}
                  color="primary"
                  name={marker.bubjungdong_name || ''}
                  count={marker.count}
                />
              ) : (
                <ListingMarker
                  onClick={() => onClickListingMarker(marker)}
                  count={marker.count}
                />
              )}
            </CustomOverlay>
          );
        })}
  • naver map - context API로 맵 객체 관리
  • CustomOverlay 컴포넌트화 - 사용하기 편하게
class OverlayView extends naver.maps.OverlayView {
  private _element: HTMLElement | undefined;

  private _position: naver.maps.LatLng;

  constructor(element: HTMLElement, position: naver.maps.LatLng) {
    super();
    this._element = element;
    this._position = position;
  }

  setPosition(position: naver.maps.LatLng) {
    this._position = position;
    this.draw();
  }

  getPosition() {
    return this._position;
  }

  onAdd() {
    if (!this._element) return;
    const { overlayLayer } = this.getPanes();
    overlayLayer.appendChild(this._element);
  }

  onRemove() {
    if (!this._element) return;
    this._element.remove();
  }

  draw() {
    if (!this.getMap() || !this._element) return;
    const projection = this.getProjection();
    const position = this.getPosition();
    const pixelPosition = projection.fromCoordToOffset(position);
    const offsetX = this._element.clientWidth / 2;
    const offsetY = this._element.clientHeight / 2;

    this._element.style.position = 'absolute';
    this._element.style.left = `${pixelPosition.x - offsetX}px`;
    this._element.style.top = `${pixelPosition.y - offsetY}px`;
  }
}

클래스로 관리

export function CustomOverlay({
  id,
  className,
  position,
  children,
}: CustomOverlayProps) {
  const map = useContext(NaverMapContext);
  const container = useRef(document.createElement('div'));

  const overlayPosition = useMemo(() => {
    if (!naver.maps) {
      return null;
    }
    return new naver.maps.LatLng(position.lat, position.lng);
  }, [position.lat, position.lng]);

  const overlay = useMemo(() => {
    if (overlayPosition) {
      return new OverlayView(container.current, overlayPosition);
    }

    return null;
  }, [overlayPosition]);

  useEffect(() => {
    if (!map) return () => {};
    overlay?.setMap(map);
    return () => {
      overlay?.setMap(null);
    };
  }, [map, overlay]);

  useEffect(() => {
    if (overlayPosition) {
      overlay?.setPosition(overlayPosition);
    }
  }, [overlay, overlayPosition]);

  useEffect(() => {
    if (id) container.current.id = id;
  }, [id]);

  useEffect(() => {
    if (className) container.current.className = className;
  }, [className]);

  return ReactDOM.createPortal(children, container.current);
}

createPortal

재조정

profile
코딩과 독서 그리고 침착맨을 좋아해요

0개의 댓글