Skip to content

Commit

Permalink
[FE][Feat] #249 : 지도와 캔버스 연동 및 완성
Browse files Browse the repository at this point in the history
- 사용하지 않는 파일 제거
  • Loading branch information
happyhyep committed Nov 25, 2024
1 parent 0f28fa5 commit c5242d2
Show file tree
Hide file tree
Showing 3 changed files with 164 additions and 171 deletions.
172 changes: 86 additions & 86 deletions frontend/src/component/canvas/useEventHandlers.tsx
Original file line number Diff line number Diff line change
@@ -1,86 +1,86 @@
import { useRef } from 'react';
import { ICanvasRefMethods } from '@/component/canvas/Canvas.tsx';
import { IMapObject, IMapRefMethods } from '@/component/maps/Map.types.ts';

// TODO: 리팩토룅 시 null을 처리하기
interface IUseEventHandlers {
(
canvasElement: HTMLCanvasElement | null,
canvasRefMethods: ICanvasRefMethods | null,
mapElement: HTMLElement | null,
mapRefMethods: IMapRefMethods | null,
mapObject: IMapObject | null, // 비동기 로딩 시 null로 처리가 될 수 있어서 예외처리 필요
): {
handleClick: (event: React.MouseEvent) => void;
handleMouseDown: (event: React.MouseEvent) => void;
handleMouseMove: (event: React.MouseEvent) => void;
handleMouseUp: (event: React.MouseEvent) => void;
};
}

interface IMouseEventState {
isMouseDown: boolean;
mouseDownPosition: { x: number; y: number };
// mouseMovePosition: { x: number; y: number };
mouseDeltaPosition: { x: number; y: number };
}

const MouseEventStateInitialValue = {
isMouseDown: false,
mouseDownPosition: { x: 0, y: 0 },
// mouseMovePosition: { x: 0, y: 0 },
mouseDeltaPosition: { x: 0, y: 0 },
};

export const useEventHandlers: IUseEventHandlers = (
canvasElement,
canvasRefMethods,
mapElement,
mapRefMethods,
mapObject,
) => {
// if (!canvasElement || !canvasElement || !mapElement || !mapRefMethods || !mapObject)
// throw new Error('🚀 useEventHandler error : null 값이 포함되어 있습니다.');

const mouseEventState = useRef<IMouseEventState>({ ...MouseEventStateInitialValue });

const handleClick = (event: React.MouseEvent) => {
mapRefMethods?.onMouseClickHandler(event);
canvasRefMethods?.onMouseClickHandler(event);
};

const handleMouseDown = (event: React.MouseEvent) => {
if (!mapElement || !canvasElement) return;
mouseEventState.current.isMouseDown = true;
mouseEventState.current.mouseDownPosition = { x: event.clientX, y: event.clientY };
canvasRefMethods?.onMouseDownHandler(event);
};

const handleMouseMove = (event: React.MouseEvent) => {
if (!mapElement || !canvasElement || !mouseEventState.current.isMouseDown) return;

// TODO: 쓰로틀링 걸기
mouseEventState.current.mouseDeltaPosition = {
x: -(event.clientX - mouseEventState.current.mouseDownPosition.x),
y: -(event.clientY - mouseEventState.current.mouseDownPosition.y),
};

// TODO: 범용 지도에 따른 Refactoring 필요, 우선은 네이버 지도에 한해서만 수행
mapObject?.panBy(
new naver.maps.Point(
mouseEventState.current.mouseDeltaPosition.x,
mouseEventState.current.mouseDeltaPosition.y,
),
);

canvasRefMethods?.onMouseMoveHandler(event);
};

const handleMouseUp = (event: React.MouseEvent) => {
if (!mapElement || !canvasElement) return;
mouseEventState.current = { ...MouseEventStateInitialValue };
canvasRefMethods?.onMouseUpHandler(event);
};

return { handleClick, handleMouseDown, handleMouseMove, handleMouseUp };
};
// import { useRef } from 'react';
// import { ICanvasRefMethods } from '@/component/canvas/Canvas.tsx';
// import { IMapObject, IMapRefMethods } from '@/component/maps/Map.types.ts';
//
// // TODO: 리팩토룅 시 null을 처리하기
// interface IUseEventHandlers {
// (
// canvasElement: HTMLCanvasElement | null,
// canvasRefMethods: ICanvasRefMethods | null,
// mapElement: HTMLElement | null,
// mapRefMethods: IMapRefMethods | null,
// mapObject: IMapObject | null, // 비동기 로딩 시 null로 처리가 될 수 있어서 예외처리 필요
// ): {
// handleClick: (event: React.MouseEvent) => void;
// handleMouseDown: (event: React.MouseEvent) => void;
// handleMouseMove: (event: React.MouseEvent) => void;
// handleMouseUp: (event: React.MouseEvent) => void;
// };
// }
//
// interface IMouseEventState {
// isMouseDown: boolean;
// mouseDownPosition: { x: number; y: number };
// // mouseMovePosition: { x: number; y: number };
// mouseDeltaPosition: { x: number; y: number };
// }
//
// const MouseEventStateInitialValue = {
// isMouseDown: false,
// mouseDownPosition: { x: 0, y: 0 },
// // mouseMovePosition: { x: 0, y: 0 },
// mouseDeltaPosition: { x: 0, y: 0 },
// };
//
// export const useEventHandlers: IUseEventHandlers = (
// canvasElement,
// canvasRefMethods,
// mapElement,
// mapRefMethods,
// mapObject,
// ) => {
// // if (!canvasElement || !canvasElement || !mapElement || !mapRefMethods || !mapObject)
// // throw new Error('🚀 useEventHandler error : null 값이 포함되어 있습니다.');
//
// const mouseEventState = useRef<IMouseEventState>({ ...MouseEventStateInitialValue });
//
// const handleClick = (event: React.MouseEvent) => {
// mapRefMethods?.onMouseClickHandler(event);
// canvasRefMethods?.onMouseClickHandler(event);
// };
//
// const handleMouseDown = (event: React.MouseEvent) => {
// if (!mapElement || !canvasElement) return;
// mouseEventState.current.isMouseDown = true;
// mouseEventState.current.mouseDownPosition = { x: event.clientX, y: event.clientY };
// canvasRefMethods?.onMouseDownHandler(event);
// };
//
// const handleMouseMove = (event: React.MouseEvent) => {
// if (!mapElement || !canvasElement || !mouseEventState.current.isMouseDown) return;
//
// // TODO: 쓰로틀링 걸기
// mouseEventState.current.mouseDeltaPosition = {
// x: -(event.clientX - mouseEventState.current.mouseDownPosition.x),
// y: -(event.clientY - mouseEventState.current.mouseDownPosition.y),
// };
//
// // TODO: 범용 지도에 따른 Refactoring 필요, 우선은 네이버 지도에 한해서만 수행
// mapObject?.panBy(
// new naver.maps.Point(
// mouseEventState.current.mouseDeltaPosition.x,
// mouseEventState.current.mouseDeltaPosition.y,
// ),
// );
//
// canvasRefMethods?.onMouseMoveHandler(event);
// };
//
// const handleMouseUp = (event: React.MouseEvent) => {
// if (!mapElement || !canvasElement) return;
// mouseEventState.current = { ...MouseEventStateInitialValue };
// canvasRefMethods?.onMouseUpHandler(event);
// };
//
// return { handleClick, handleMouseDown, handleMouseMove, handleMouseUp };
// };
87 changes: 40 additions & 47 deletions frontend/src/component/maps/NaverMap.tsx
Original file line number Diff line number Diff line change
@@ -1,47 +1,40 @@
import { forwardRef, useEffect, useImperativeHandle, useRef, useState } from 'react';
import { setNaverMapSync } from '@/component/maps/naverMapUtils.ts';
import { IMapOptions, IMapRefMethods } from '@/component/maps/Map.types.ts';

interface INaverMapProps extends IMapOptions {
onMapInit: (map: naver.maps.Map) => void; // 콜백 프로퍼티 추가
}

export const NaverMap = forwardRef<IMapRefMethods, INaverMapProps>((props, ref) => {
const mapObject = useRef<naver.maps.Map | null>(null);
const mapContainer = useRef<HTMLElement | null>(null);

const [mapOptions, setMapOptions] = useState<IMapOptions>({
lat: props.lat,
lng: props.lng,
zoom: props.zoom,
});

useEffect(() => {
setMapOptions({
lat: props.lat,
lng: props.lng,
zoom: props.zoom,
});
}, [props.lat, props.lng, props.zoom]);

useEffect(() => {
if (mapContainer.current && mapOptions) {
mapObject.current = setNaverMapSync(mapContainer.current, mapOptions);
if (mapObject.current) props.onMapInit(mapObject.current); // 콜백 호출
}
}, [mapOptions]);

useImperativeHandle(ref, () => ({
getMapObject: () => {
if (mapObject) return mapObject.current;
throw new Error('🚀 지도 로딩 오류 : 지도 객체가 존재하지 않습니다.');
},
getMapContainer: () => {
if (mapContainer) return mapContainer.current;
throw new Error('🚀 지도 로딩 오류 : 지도 컨테이너가 존재하지 않습니다.');
},
onMouseClickHandler: () => {},
}));

return <section ref={mapContainer} className="h-full w-full" />;
});
// import { forwardRef, useEffect, useImperativeHandle, useRef, useState } from 'react';
// import { setNaverMapSync } from '@/component/maps/naverMapUtils.ts';
// import { IMapOptions, IMapRefMethods } from '@/component/maps/Map.tsx';
//
// interface INaverMapProps extends IMapOptions {
// onMapInit: (map: naver.maps.Map) => void; // 콜백 프로퍼티 추가
// }
//
// export const NaverMap = forwardRef<IMapRefMethods, INaverMapProps>((props, ref) => {
// const naverMapObject = useRef<naver.maps.Map | null>(null);
// const naverMapContainer = useRef<HTMLElement | null>(null);
// const [mapOptions, setMapOptions] = useState<IMapOptions>({
// lat: props.lat,
// lng: props.lng,
// zoom: props.zoom,
// });
//
// useEffect(() => {
// setMapOptions({
// lat: props.lat,
// lng: props.lng,
// zoom: props.zoom,
// });
// }, [props.lat, props.lng, props.zoom]);
//
// useEffect(() => {
// if (naverMapContainer.current && mapOptions !== null) {
// naverMapObject.current = setNaverMapSync(naverMapContainer.current, mapOptions);
// if (naverMapObject.current !== null) props.onMapInit(naverMapObject.current); // 콜백 호출
// }
// }, [mapOptions]);
//
// useImperativeHandle(ref, () => ({
// getMapObject: () => naverMapObject.current,
// getMapContainer: () => naverMapContainer.current,
// onMouseClickHandler: () => {},
// }));
//
// return <section ref={naverMapContainer} className="h-full w-full" />;
// });
76 changes: 38 additions & 38 deletions frontend/src/component/maps/naverMapUtils.ts
Original file line number Diff line number Diff line change
@@ -1,38 +1,38 @@
import { IMapOptions } from '@/component/maps/Map.types.ts';

export const setNaverMapOption = (mapOptions: IMapOptions): IMapOptions => {
return {
...mapOptions,
lat: mapOptions.lat ? mapOptions.lat : 37.42829747263545,
lng: mapOptions.lng ? mapOptions.lng : 126.76620435615891,
zoom: mapOptions.zoom ? mapOptions.zoom : 20,
};
};

export const setNaverMap = (
htmlElement: HTMLElement,
mapOptions: IMapOptions,
): Promise<naver.maps.Map> => {
const { lat, lng, ...restProps } = setNaverMapOption(mapOptions);

return new Promise(resolve => {
const map = new naver.maps.Map(htmlElement, {
center: new naver.maps.LatLng(lat, lng),
...restProps,
});

resolve(map);
});
};

export const setNaverMapSync = (
htmlElement: HTMLElement,
mapOptions: IMapOptions,
): naver.maps.Map => {
const { lat, lng, ...restProps } = setNaverMapOption(mapOptions);

return new naver.maps.Map(htmlElement, {
center: new naver.maps.LatLng(lat, lng),
...restProps,
});
};
// import { IMapOptions } from '@/component/maps/Map.types.ts';
//
// export const setNaverMapOption = (mapOptions: IMapOptions): IMapOptions => {
// return {
// ...mapOptions,
// lat: mapOptions.lat ? mapOptions.lat : 37.42829747263545,
// lng: mapOptions.lng ? mapOptions.lng : 126.76620435615891,
// zoom: mapOptions.zoom ? mapOptions.zoom : 20,
// };
// };
//
// export const setNaverMap = (
// htmlElement: HTMLElement,
// mapOptions: IMapOptions,
// ): Promise<naver.maps.Map> => {
// const { lat, lng, ...restProps } = setNaverMapOption(mapOptions);
//
// return new Promise(resolve => {
// const map = new naver.maps.Map(htmlElement, {
// center: new naver.maps.LatLng(lat, lng),
// ...restProps,
// });
//
// resolve(map);
// });
// };
//
// export const setNaverMapSync = (
// htmlElement: HTMLElement,
// mapOptions: IMapOptions,
// ): naver.maps.Map => {
// const { lat, lng, ...restProps } = setNaverMapOption(mapOptions);
//
// return new naver.maps.Map(htmlElement, {
// center: new naver.maps.LatLng(lat, lng),
// ...restProps,
// });
// };

0 comments on commit c5242d2

Please sign in to comment.