Skip to content

Commit

Permalink
Merge pull request #480 from boostcampwm2023/map-개선
Browse files Browse the repository at this point in the history
[Refactor] Tmap 렌더링 속도 개선을 위한 스펙 변경 (Tmapv2 → Tmpav3)
  • Loading branch information
ttaerrim authored Dec 13, 2023
2 parents 5380f20 + 75354b5 commit 5d224f1
Show file tree
Hide file tree
Showing 11 changed files with 77 additions and 49 deletions.
2 changes: 1 addition & 1 deletion app/frontend/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,6 @@
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
<script src="https://apis.openapi.sk.com/tmap/jsv2?version=1&appKey=F5KgoZ8bWF1IR9Lin2t0V4zxO3ISI7ndSO8EsEq1"></script>
<script src="https://apis.openapi.sk.com/tmap/vectorjs?version=1&appKey=F5KgoZ8bWF1IR9Lin2t0V4zxO3ISI7ndSO8EsEq1"></script>
</body>
</html>
4 changes: 4 additions & 0 deletions app/frontend/src/assets/icons/marker-green.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions app/frontend/src/assets/icons/marker-red.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
26 changes: 18 additions & 8 deletions app/frontend/src/components/Map/Marker.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,33 @@
import { ReactComponent as Pin } from '@/assets/icons/pin.svg';
import { TMap, TMapLatLng } from '@/types';
import { reactElementToString } from '@/utils';

import * as styles from './index.css';

const { Tmapv2 } = window;
const { Tmapv3 } = window;

type MarkerProps = {
mapContent: TMap;
position: TMapLatLng;
theme: 'green' | 'red';
icon?: string;
labelText?: string;
};

export const Marker = ({ mapContent, position, theme }: MarkerProps) =>
new Tmapv2.Marker({
export function Marker({
mapContent,
position,
theme,
labelText,
}: MarkerProps) {
return new Tmapv3.Marker({
position,
iconHTML: reactElementToString(
<Pin className={styles.marker({ theme })} width={50} height={50} />,
),
iconSize: new Tmapv2.Size(50, 50),
map: mapContent,
icon: `/src/assets/icons/marker-${theme}.svg`,
iconSize: new Tmapv3.Size(50, 50),
label: labelText
? reactElementToString(
<span className={styles.label({ theme })}>{labelText}</span>,
)
: '',
});
}
9 changes: 8 additions & 1 deletion app/frontend/src/components/Map/index.css.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { style } from '@vanilla-extract/css';
import { style, globalStyle } from '@vanilla-extract/css';
import { recipe } from '@vanilla-extract/recipes';

import { vars, fontStyle } from '@/styles';
Expand All @@ -22,6 +22,7 @@ export const label = recipe({
top: '-6.5rem',
left: '50%',
transform: 'translate(-50%)',
whiteSpace: 'pre',
},
],
variants: {
Expand Down Expand Up @@ -70,3 +71,9 @@ export const myLocation = style({
boxShadow: '0px 0px 8px 0px rgba(0 0 0 / 0.25)',
zIndex: '10',
});

globalStyle('.marker-image', {
width: '5rem',
height: '5rem',
zIndex: '1',
});
28 changes: 9 additions & 19 deletions app/frontend/src/components/Map/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,12 @@ import 'dayjs/locale/ko';
import { MAX_ZOOM_LEVEL } from '@/constants';
import { useMap } from '@/hooks';
import { queryKeys } from '@/queries';
import { reactElementToString } from '@/utils';

import * as styles from './index.css';
import { Marker } from './Marker';
import { MyLocation } from './MyLocation';

const { Tmapv2 } = window;
const { Tmapv3 } = window;
dayjs.locale('ko');

type MapProps = {
Expand All @@ -33,20 +32,21 @@ type UpdateMarker = (
longitude: number | null;
},
theme: 'green' | 'red',
labelText: string,
) => void;

const setMyLocation = (updateMarker: UpdateMarker) => {
const onSuccess = (position: Geolocation) => {
const { latitude, longitude } = position.coords;
updateMarker({ latitude, longitude }, 'red');
updateMarker({ latitude, longitude }, 'red', '현 위치');
};
navigator.geolocation.getCurrentPosition(onSuccess);
};

export function Map({ onClickMarker, closeSidebar }: MapProps) {
const { data: mogacoList } = useQuery(queryKeys.mogaco.list());
const mapRef = useRef<HTMLDivElement>(null);
const { mapInstance, updateMarker, currentMarker } = useMap(mapRef);
const { mapInstance, updateMarker } = useMap(mapRef);
const onClickMyLocation = () => {
closeSidebar();
setMyLocation(updateMarker);
Expand All @@ -61,36 +61,26 @@ export function Map({ onClickMarker, closeSidebar }: MapProps) {
if (!mapInstance) {
return;
}
currentMarker?.setLabel(
reactElementToString(
<span className={styles.label({ theme: 'red' })}>현 위치</span>,
),
);

mogacoList?.forEach((mogaco: ResponseMogacoDto) => {
const { id, latitude, longitude } = mogaco;
if (latitude && longitude) {
const position = new Tmapv2.LatLng(latitude, longitude);
const position = new Tmapv3.LatLng(latitude, longitude);
const marker = Marker({
mapContent: mapInstance,
position,
theme: 'green',
labelText: dayjs(mogaco.date).format('MM/DD(ddd) HH:mm'),
});
marker.addListener('click', () => {
marker.on('Click', () => {
onClickMarker(id);
mapInstance.setCenter(position);
mapInstance.setZoom(MAX_ZOOM_LEVEL);
});
marker.setLabel(
reactElementToString(
<span className={styles.label({ theme: 'green' })}>
{dayjs(mogaco.date).format('MM/DD(ddd) HH:mm')}
</span>,
),
);
}
});
}, [mogacoList, currentMarker, mapInstance, onClickMarker]);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [mogacoList]);

return (
<div className={styles.container}>
Expand Down
18 changes: 11 additions & 7 deletions app/frontend/src/components/Modal/MapModal/useMap.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
/* eslint-disable no-underscore-dangle */
import { useCallback, useEffect, useState } from 'react';

import { keepPreviousData, useQuery } from '@tanstack/react-query';

import { Marker } from '@/components/Map/Marker';
import {
DEFAULT_ZOOM_LEVEL,
INITIAL_LATITUDE,
INITIAL_LONGITUDE,
MAX_ZOOM_LEVEL,
MIN_ZOOM_LEVEL,
} from '@/constants';
import { queryKeys } from '@/queries';
import { TMap, TMapEvent, TMapLatLng, TMapMarker } from '@/types';

const { Tmapv2 } = window;
const { Tmapv3 } = window;

export const useMap = (mapRef: React.RefObject<HTMLDivElement>) => {
const [mapInstance, setMapInstance] = useState<TMap | null>(null);
Expand Down Expand Up @@ -67,9 +70,10 @@ export const useMap = (mapRef: React.RefObject<HTMLDivElement>) => {
return;
}

const map = new Tmapv2.Map('map', {
const map = new Tmapv3.Map('map', {
zoom: DEFAULT_ZOOM_LEVEL,
zoomControl: false,
center: new Tmapv3.LatLng(INITIAL_LATITUDE, INITIAL_LONGITUDE),
});

map.setZoomLimit(MIN_ZOOM_LEVEL, MAX_ZOOM_LEVEL);
Expand All @@ -82,13 +86,13 @@ export const useMap = (mapRef: React.RefObject<HTMLDivElement>) => {
}

const renderMarker = (e: TMapEvent) => {
const { latLng } = e;
const position = new Tmapv2.LatLng(latLng.lat(), latLng.lng());
const { lngLat } = e.data;
const position = new Tmapv3.LatLng(lngLat._lat, lngLat._lng);

setCurrentCoord(position);
};

mapInstance.addListener('click', renderMarker);
mapInstance.on('Click', renderMarker);
}, [mapInstance, currentCoord]);

const updateMarker = useCallback(
Expand All @@ -101,7 +105,7 @@ export const useMap = (mapRef: React.RefObject<HTMLDivElement>) => {
return;
}

const position = new Tmapv2.LatLng(latitude, longitude);
const position = new Tmapv3.LatLng(latitude, longitude);

setCurrentCoord(position);
mapInstance?.setCenter(position);
Expand All @@ -110,7 +114,7 @@ export const useMap = (mapRef: React.RefObject<HTMLDivElement>) => {
);

const setCoord = (currCoord: { latitude: number; longitude: number }) => {
const position = new Tmapv2.LatLng(currCoord.latitude, currCoord.longitude);
const position = new Tmapv3.LatLng(currCoord.latitude, currCoord.longitude);
setCurrentCoord(position);
setCenterToSelectedCoord(position);
};
Expand Down
2 changes: 2 additions & 0 deletions app/frontend/src/constants/Map.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
export const DEFAULT_ZOOM_LEVEL = 16;
export const INITIAL_LATITUDE = 37.566481622437934;
export const INITIAL_LONGITUDE = 126.98502302169841;
export const MAX_ZOOM_LEVEL = 17;
export const MIN_ZOOM_LEVEL = 7;
16 changes: 10 additions & 6 deletions app/frontend/src/hooks/useMap.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable no-underscore-dangle */
import { useCallback, useEffect, useState } from 'react';

import { Marker } from '@/components/Map/Marker';
Expand All @@ -8,7 +9,7 @@ import {
} from '@/constants';
import { TMap, TMapMarker } from '@/types';

const { Tmapv2 } = window;
const { Tmapv3 } = window;

export const useMap = (mapRef: React.RefObject<HTMLDivElement>) => {
const [mapInstance, setMapInstance] = useState<TMap | null>(null);
Expand All @@ -19,7 +20,7 @@ export const useMap = (mapRef: React.RefObject<HTMLDivElement>) => {
return;
}

const map = new Tmapv2.Map('map', {
const map = new Tmapv3.Map('map', {
zoom: DEFAULT_ZOOM_LEVEL,
zoomControl: false,
});
Expand All @@ -32,6 +33,7 @@ export const useMap = (mapRef: React.RefObject<HTMLDivElement>) => {
(
coord: { latitude: number | null; longitude: number | null },
theme: 'green' | 'red',
labelText?: string,
) => {
const { latitude, longitude } = coord;
if (!(latitude && longitude) || !mapInstance) {
Expand All @@ -40,21 +42,23 @@ export const useMap = (mapRef: React.RefObject<HTMLDivElement>) => {

if (currentMarker) {
const currMarker = currentMarker.getPosition();
const prevLatitude = currMarker.lat();
const prevLongitude = currMarker.lng();
const prevLatitude = currMarker._lat;
const prevLongitude = currMarker._lng;
if (prevLatitude === latitude && prevLongitude === longitude) {
mapInstance?.setCenter(new Tmapv2.LatLng(latitude, longitude));
mapInstance?.setCenter(new Tmapv3.LatLng(latitude, longitude));
mapInstance?.setZoom(DEFAULT_ZOOM_LEVEL);
return;
}
}

currentMarker?.setMap(null);
const position = new Tmapv2.LatLng(latitude, longitude);
const position = new Tmapv3.LatLng(latitude, longitude);

const marker = Marker({
mapContent: mapInstance,
position,
theme,
labelText,
});
setCurrentMarker(marker);
mapInstance?.setCenter(position);
Expand Down
4 changes: 3 additions & 1 deletion app/frontend/src/types/global.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { TMapLatLng, TMap, TMapSize } from './tmap';

declare global {
interface Window {
Tmapv2: {
Tmapv3: {
Map: new (
element: HTMLElement | string,
options?: {
Expand All @@ -20,6 +20,8 @@ declare global {
position: TMapLatLng;
iconHTML?: string;
iconSize?: TMapSize;
label?: string;
icon?: string;
}) => TMapMarker;
Size: new (width: number, height: number) => TMapSize;
};
Expand Down
13 changes: 7 additions & 6 deletions app/frontend/src/types/tmap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,18 +40,19 @@ export type TMap = {
setZoom: (zoomLevel: number) => void;
setOptions: ({ zoomControl }: MapOptions) => void;
destroy: () => void;
addListener: (
eventType: EventType,
listener: (event: TMapEvent) => void,
) => void;
on: (eventType: EventType, listener: (event: TMapEvent) => void) => void;
};
type EventType = 'click';
type EventType = 'Click';
export type TMapEvent = {
latLng: TMapLatLng;
data: {
lngLat: TMapLatLng;
};
};
export type TMapLatLng = {
lat: () => number;
lng: () => number;
_lat: number;
_lng: number;
};

export type TMapMarker = {
Expand Down

0 comments on commit 5d224f1

Please sign in to comment.