Skip to content

Commit

Permalink
[FE] Refactor/#613 지도 클러스터링 기능 추가 및 지도 상태 리팩토링 (#615)
Browse files Browse the repository at this point in the history
* fix: Flex 컴포넌트를 상속받는 로컬 스타일드 컴포넌트 타입 오류 해결

Flex를 상속받은 로컬 스타일드 컴포넌트에 특정 제네릭 prop을 추가하면 Box 컴포넌트까지 타입 검사가 내려간다.
이로 인해 Box 컴포넌트에 Flex 컴포넌트 인터페이스를 찾는 타입 오류가 생겨 이 문제를 Flex와 Box간 상속관계를 끊음으로 해결한다.

* refactor: map 인스턴스 전역상태 분리로 각종 hook 리팩토링

* refactor: 지도 타입 추가

* chore: eslint 설정 변경

* refactor: map type 추가

* refactor: mapInstance interface 명 수정

* refactor: 핀 svg 사이즈 일괄 60px로 지정

* refactor: 클러스터 적용으로 인한 map 인터렉션 로직 수정

* fix: drag 디바운스 적용 및 pin 정보 가져오는 로직 오류 수정

* refactor: pinSize 상수화 및 일부 파일 개행 수정

* fix: off 함수 타입 추가 및 클러스터링 중복 요청 오류 해결

* refactor: screen size 에 해당하는 marker만 그리는 로직 이동

* refactor: event 타입 변경 및 sidebar 전역 상태 제거

zoom 일 경우에만 실제 서버에 클러스터 핀 갱신 요청을 보내고 dragEnd 상태에서는 보내지 않도록 한다.
sidebarMarkers 는 잠시 사용을 보류한다.

* refactor: map 및 markers 의존성 제거

* design: 클러스터된 핀 디자인 변경

* fix: map 드래그 경우 클로저 문제로 인한 핀 갱신 오류 수정

* refactor: 최고 줌인 상태에서 클러스터 핀 상태일 때 infoWindow에 모두 표시하도록 변경

* refactor: 불필요한 import 제거

* refactor: mock 데이터에서 실제 서버 요청으로 변경

* refactor: UI 변경사항 대응
  • Loading branch information
semnil5202 authored Nov 7, 2023
1 parent da2c754 commit 206fd06
Show file tree
Hide file tree
Showing 14 changed files with 380 additions and 108 deletions.
2 changes: 1 addition & 1 deletion frontend/.eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ module.exports = {
'no-unused-expressions': 'off',
'react/jsx-props-no-spreading': 'off',
'react/no-unused-prop-types': 'off',
'import/no-extraneous-dependencies': 'off',
'no-underscore-dangle': 'off',
},
settings: {
'import/resolver': {
Expand Down
20 changes: 10 additions & 10 deletions frontend/src/components/Map/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ const getZoomMinLimit = () => {

function Map() {
const { Tmapv3 } = window;

const { markers } = useContext(MarkerContext);
const { width } = useContext(LayoutWidthContext);
const { mapInstance, setMapInstance } = useMapStore((state) => state);
Expand All @@ -47,26 +46,25 @@ function Map() {
const map = new Tmapv3.Map(mapContainer.current, {
center: new Tmapv3.LatLng(37.5154, 127.1029),
scaleBar: false,
width: '100%',
height: '100%',
});

if (!map) return;

map.setZoomLimit(getZoomMinLimit(), 17);

setMapInstance(map);

// eslint-disable-next-line consistent-return
return () => {
map.destroy();
};
}, []);

useMapClick(mapInstance);
useClickedCoordinate(mapInstance);
useUpdateCoordinates(mapInstance);
useMapClick();
useClickedCoordinate();
useUpdateCoordinates();

useFocusToMarker(mapInstance, markers);
onFocusClickedPin(mapInstance, markers);
useFocusToMarker(markers);
onFocusClickedPin();

return (
<MapContainer>
Expand All @@ -84,6 +82,8 @@ function Map() {
}

const MapContainer = styled.div`
width: 100%;
height: 100%;
position: relative;
`;

Expand Down Expand Up @@ -116,4 +116,4 @@ const CurrentLocationIcon = styled(CurrentLocation)`
}
`;

export default Map;
export default Map;
67 changes: 64 additions & 3 deletions frontend/src/components/common/Flex/index.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import { styled } from 'styled-components';

import Box, { BoxProps } from '../Box';
import theme from '../../../themes';
import { colorThemeKey } from '../../../themes/color';
import { radiusKey } from '../../../themes/radius';
import { SpaceThemeKeys } from '../../../themes/spacing';

interface FlexProps extends BoxProps {
interface FlexProps {
$flexDirection?: string;
$flexWrap?: string;
$flexBasis?: string;
Expand All @@ -14,9 +17,34 @@ interface FlexProps extends BoxProps {
$justifyItems?: string;
flex?: string;
$gap?: string;

width?: string;
height?: string;
$minWidth?: string;
$minHeight?: string;
$maxWidth?: string;
$maxHeight?: string;
padding?: SpaceThemeKeys | string;
$backgroundColor?: colorThemeKey;
$backdropFilter?: string;
overflow?: string;
color?: colorThemeKey;
position?: string;
right?: string;
top?: string;
left?: string;
bottom?: string;
$borderRadius?: radiusKey;
$borderTop?: string;
$borderRight?: string;
$borderBottom?: string;
$borderLeft?: string;
cursor?: string;
opacity?: string;
$zIndex?: number;
}

const Flex = styled(Box)<FlexProps>`
const Flex = styled.div<FlexProps>`
display: flex;
flex-direction: ${({ $flexDirection }) => $flexDirection};
flex-wrap: ${({ $flexWrap }) => $flexWrap};
Expand All @@ -29,6 +57,39 @@ const Flex = styled(Box)<FlexProps>`
justify-items: ${({ $justifyItems }) => $justifyItems};
flex: ${({ flex }) => flex};
gap: ${({ $gap }) => $gap};
background-color: ${({ $backgroundColor }) =>
$backgroundColor && theme.color[$backgroundColor]};
backdrop-filter: ${({ $backdropFilter }) => $backdropFilter};
color: ${({ color }) => color && theme.color[color]};
padding: ${({ padding }) => padding && convertPadding(padding)};
width: ${({ width }) => width};
height: ${({ height }) => height};
min-width: ${({ $minWidth }) => $minWidth};
min-height: ${({ $minHeight }) => $minHeight};
max-width: ${({ $maxWidth }) => $maxWidth};
max-height: ${({ $maxHeight }) => $maxHeight};
overflow: ${({ overflow }) => overflow};
position: ${({ position }) => position};
right: ${({ right }) => right};
top: ${({ top }) => top};
left: ${({ left }) => left};
bottom: ${({ bottom }) => bottom};
border-radius: ${({ $borderRadius }) =>
$borderRadius && theme.radius[$borderRadius]};
border-top: ${({ $borderTop }) => $borderTop};
border-right: ${({ $borderRight }) => $borderRight};
border-bottom: ${({ $borderBottom }) => $borderBottom};
border-left: ${({ $borderLeft }) => $borderLeft};
cursor: ${({ cursor }) => cursor};
opacity: ${({ opacity }) => opacity};
z-index: ${({ $zIndex }) => $zIndex};
`;

const convertPadding = (padding: SpaceThemeKeys | string) => {
if (typeof padding === 'string' && padding.length > 1) return padding;

return theme.spacing[Number(padding)];
};

export default Flex;
2 changes: 2 additions & 0 deletions frontend/src/constants/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,5 @@ export const DEFAULT_PROFILE_IMAGE =

export const DEFAULT_PROD_URL =
process.env.APP_URL || 'https://mapbefine.kro.kr/api';

export const PIN_SIZE = 60;
51 changes: 44 additions & 7 deletions frontend/src/constants/pinImage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export const USER_LOCATION_IMAGE = `<svg width="24" height="24" viewBox="0 0 24
`;

export const pinImageMap: PinImageMap = {
1: `<svg width="40" height="58" viewBox="0 0 40 58" fill="none" xmlns="http://www.w3.org/2000/svg">
1: `<svg width="60" height="60" viewBox="0 0 40 58" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M10.8449 48.4877C9.81988 49.803 7.73559 48.7147 8.22893 47.1219L14.5909 26.5813C14.868 25.6867 15.8879 25.262 16.718 25.6954L23.5743 29.2752C24.4044 29.7086 24.6388 30.7883 24.0632 31.5269L10.8449 48.4877Z" fill="#454545"/>
<circle cx="23.9766" cy="16" r="16" fill="#E1325C"/>
<circle cx="17.7548" cy="8.88856" r="3.55556" fill="white" fill-opacity="0.6"/>
Expand All @@ -18,7 +18,7 @@ export const pinImageMap: PinImageMap = {
<circle cx="27.0872" cy="17.3333" r="1.33333" fill="black"/>
</svg>
`,
2: `<svg width="40" height="58" viewBox="0 0 40 58" fill="none" xmlns="http://www.w3.org/2000/svg">
2: `<svg width="60" height="60" viewBox="0 0 40 58" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M10.8449 48.4877C9.81988 49.803 7.73559 48.7147 8.22893 47.1219L14.5909 26.5813C14.868 25.6867 15.8879 25.262 16.718 25.6954L23.5743 29.2752C24.4044 29.7086 24.6388 30.7883 24.0632 31.5269L10.8449 48.4877Z" fill="#454545"/>
<circle cx="23.9766" cy="16" r="16" fill="#F9CB55"/>
<circle cx="17.7548" cy="8.88856" r="3.55556" fill="white" fill-opacity="0.6"/>
Expand All @@ -27,7 +27,7 @@ export const pinImageMap: PinImageMap = {
<circle cx="27.0872" cy="17.3333" r="1.33333" fill="black"/>
</svg>
`,
3: `<svg width="40" height="58" viewBox="0 0 40 58" fill="none" xmlns="http://www.w3.org/2000/svg">
3: `<svg width="60" height="60" viewBox="0 0 40 58" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M10.8449 48.4877C9.81988 49.803 7.73559 48.7147 8.22893 47.1219L14.5909 26.5813C14.868 25.6867 15.8879 25.262 16.718 25.6954L23.5743 29.2752C24.4044 29.7086 24.6388 30.7883 24.0632 31.5269L10.8449 48.4877Z" fill="#454545"/>
<circle cx="23.9766" cy="16" r="16" fill="#4B5CFA"/>
<circle cx="17.7548" cy="8.88856" r="3.55556" fill="white" fill-opacity="0.6"/>
Expand All @@ -36,7 +36,7 @@ export const pinImageMap: PinImageMap = {
<circle cx="27.0872" cy="17.3333" r="1.33333" fill="black"/>
</svg>
`,
4: `<svg width="40" height="58" viewBox="0 0 40 58" fill="none" xmlns="http://www.w3.org/2000/svg">
4: `<svg width="60" height="60" viewBox="0 0 40 58" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M10.8449 48.4877C9.81988 49.803 7.73559 48.7147 8.22893 47.1219L14.5909 26.5813C14.868 25.6867 15.8879 25.262 16.718 25.6954L23.5743 29.2752C24.4044 29.7086 24.6388 30.7883 24.0632 31.5269L10.8449 48.4877Z" fill="#454545"/>
<circle cx="23.9766" cy="16" r="16" fill="#57B148"/>
<circle cx="17.7548" cy="8.88856" r="3.55556" fill="white" fill-opacity="0.6"/>
Expand All @@ -45,7 +45,7 @@ export const pinImageMap: PinImageMap = {
<circle cx="27.0872" cy="17.3333" r="1.33333" fill="black"/>
</svg>
`,
5: `<svg width="40" height="58" viewBox="0 0 40 58" fill="none" xmlns="http://www.w3.org/2000/svg">
5: `<svg width="60" height="60" viewBox="0 0 40 58" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M10.8449 48.4877C9.81988 49.803 7.73559 48.7147 8.22893 47.1219L14.5909 26.5813C14.868 25.6867 15.8879 25.262 16.718 25.6954L23.5743 29.2752C24.4044 29.7086 24.6388 30.7883 24.0632 31.5269L10.8449 48.4877Z" fill="#454545"/>
<circle cx="23.9766" cy="16" r="16" fill="#2AC1BC"/>
<circle cx="17.7548" cy="8.88856" r="3.55556" fill="white" fill-opacity="0.6"/>
Expand All @@ -54,7 +54,7 @@ export const pinImageMap: PinImageMap = {
<circle cx="27.0872" cy="17.3333" r="1.33333" fill="black"/>
</svg>
`,
6: `<svg width="40" height="58" viewBox="0 0 40 58" fill="none" xmlns="http://www.w3.org/2000/svg">
6: `<svg width="60" height="60" viewBox="0 0 40 58" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M10.8449 48.4877C9.81988 49.803 7.73559 48.7147 8.22893 47.1219L14.5909 26.5813C14.868 25.6867 15.8879 25.262 16.718 25.6954L23.5743 29.2752C24.4044 29.7086 24.6388 30.7883 24.0632 31.5269L10.8449 48.4877Z" fill="#454545"/>
<circle cx="23.9766" cy="16" r="16" fill="#FD842D"/>
<circle cx="17.7548" cy="8.88856" r="3.55556" fill="white" fill-opacity="0.6"/>
Expand All @@ -63,7 +63,7 @@ export const pinImageMap: PinImageMap = {
<circle cx="27.0872" cy="17.3333" r="1.33333" fill="black"/>
</svg>
`,
7: `<svg width="40" height="58" viewBox="0 0 40 58" fill="none" xmlns="http://www.w3.org/2000/svg">
7: `<svg width="60" height="60" viewBox="0 0 40 58" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M10.8449 48.4877C9.81988 49.803 7.73559 48.7147 8.22893 47.1219L14.5909 26.5813C14.868 25.6867 15.8879 25.262 16.718 25.6954L23.5743 29.2752C24.4044 29.7086 24.6388 30.7883 24.0632 31.5269L10.8449 48.4877Z" fill="#454545"/>
<circle cx="23.9766" cy="16" r="16" fill="#C340B6"/>
<circle cx="17.7548" cy="8.88856" r="3.55556" fill="white" fill-opacity="0.6"/>
Expand All @@ -83,3 +83,40 @@ export const pinColors: PinImageMap = {
6: '#FD842D',
7: '#C340B6',
};

export const getInfoWindowTemplate = ({
backgroundColor,
pinName,
pins,
condition,
}: {
backgroundColor: string;
pinName: string;
pins: [];
condition: number;
}) => `
<div style="position: relative;">
${
condition !== 1
? pins
.map(
(
pin: any,
) => `<div style="border-bottom: 1px solid white; padding: 4px 12px; display:flex; border-radius: 20px; justify-content: center; align-items: center; height:32px; font-size:14px; color:#ffffff; background-color: ${backgroundColor};">
${pin.name}
</div>`,
)
.join('')
: `<div style="padding: 4px 12px; display:flex; border-radius: 20px; justify-content: center; align-items: center; height:32px; font-size:14px; color:#ffffff; background-color: ${backgroundColor};">
${pinName}
</div>
${
pins.length > 1
? `
<div style="position: absolute; top: -14px; right: -12px; padding: 2px 4px; font-size: 14px; background-color: #fff; border-radius: 50%; border: 1px solid ${backgroundColor}; color: ${backgroundColor}">+${pins.length}</div>
`
: ''
}
</div>`
}
`;
Loading

0 comments on commit 206fd06

Please sign in to comment.