[React] 카카오 Map API - Polyline Map

또여·2021년 8월 26일
0

React 프로젝트

목록 보기
6/20
post-custom-banner

지난번에 이어 변경된 부분이 있어서 추가하려고 한다

0. 결과물


이런식으로 설계 및 개념을 잡아가며 진행중


현재 구성된 UI

1. Map 마커 및 선(Polyline) 초기화

상위 컴포넌트(EditPage.js)에서 Map 컴포넌트로 현재 조회된 List를 내려준다

기존과 바꾼 개념적 부분은 157~160 라인

onDrawMap 함수 내에서만 지도의 마커와 선을 활용하게 되어서,, 다른 컴포넌트는 물론 다른 함수에서도 사용이 안되었다
그래서 지도에 마커와 선이 그려질 때, 그 객체를 setState(159~160 라인)해서 이 컴포넌트는 물론 외부컴포넌트에서도 사용 할 수 있도록 해주었다.

onDrawMap을 하기 전에 onClearMap을 먼저 해주지 않으면, 기존에 setState로 그려진 마커와 선이 중복되어 쌓이게 된다. 그래서 73~74 라인처럼 setMap(null)을 해주면 기존에 Map에 그려진 선과 마커를 지워주고, setState도 비워준 후 MapFlag로 다시 그려주는 식으로 표현했다

2. 남은 작업

  • 하루치 데이터가 Props로 넘어오는데, 이때 동적으로 화면의 중심좌표와 줌레벨 설정
  • 마커, 선에 저장된 데이터가 있는 경우와 없는 경우 구분

3. Map.js 소스

import React, { useRef, useEffect, useState } from 'react'
import _ from 'lodash';

/*
    placeId: nullable
    address: nullabe
    point Array: lat, lng 위도 경도
    name: nullable
    startTiem, endTime: Timestamp
    activityType: Stay면 null / WALKING BUS TRAIN ...
    index: index
    visitType: MOVE / STAY
*/

/*
    Map[Kakao Map]: Map 지도
    ReadData[Array]: API로 읽어온 데이터 저장해놓는 변수
    CurPolylineIdx[Number]: 마커나 라인 선택하였을때 index값을 저장
    PolylineList[Array]: 그려야하는 Polyline List
    MakerList[Array]: 그려야하는 Maker List


    updatePolyline: props 상위로 선택한 라인의 index를 올림
*/
const lineColor = {
    "WALKING": "#ffc952",
    "BUS":"#34314c",
    "SUBWAY":"#47b8e0",
    "RUNNING":"#99f19e",
    "ETC":"#ff7473"
}

function Map(props) {
    const kakaoAPI = window.kakao.maps
    const [Map, setMap] = useState()
    const [CurData, setCurData] = useState()
    const [CurPolylineIdx, setCurPolylineIdx] = useState()
    const [MapFlag, setMapFlag] = useState(false)
    const [PolylineList, setPolylineList] = useState([])
    const [MarkerList, setMarkerList] = useState([])

    const options = {
        //지도를 생성할 때 필요한 기본 옵션
        center: new kakaoAPI.LatLng(37.5559908, 126.9741218), //지도의 중심좌표.
        level: 8, //지도의 레벨(확대, 축소 정도)
    }

    const container = useRef(null) //지도를 담을 영역의 DOM 레퍼런스

    useEffect(() => {
        setMap(new kakaoAPI.Map(container.current, options)) //지도 생성 및 객체 리턴
    }, [])

    useEffect(() => {
        setCurData(props.polyline)
    }, [props.polyline])

    useEffect(() => {
        onClearMap()
    }, [CurData])

    useEffect(() => {
        onDrawMap()
    }, [MapFlag])

    useEffect(() => {
        if(CurPolylineIdx) {
            props.updateSelectedIdx(CurPolylineIdx)
        }
    }, [CurPolylineIdx])

    const onClearMap = () => {
        PolylineList.map((cur) => cur.setMap(null))
        MarkerList.map((cur) => cur.setMap(null))
        setPolylineList([])
        setMarkerList([])
        setMapFlag(!MapFlag)
    }
    
    const onDrawMap = () => {
        let tempPolyline = []
        let tempMarker = []
        CurData && CurData.map((cur) => {
            //console.log(cur)
            if(cur.visitType === 'STAY'){
                let marker = new kakaoAPI.Marker({
                    map: Map,
                    position: new kakaoAPI.LatLng(cur.point[0].lat , cur.point[0].lng),
                    title: cur.name
                })
                
                kakaoAPI.event.addListener(marker, 'click', function() {
                    setCurPolylineIdx(cur.index)
                })
                //marker.setMap(Map)
                tempMarker.push(marker)
            } else {
                let pathPoint = []
                cur.point.map((p) => {
                    pathPoint.push(new kakaoAPI.LatLng(p.lat, p.lng))
                })
                
                let polylineColor// = '#' +  Math.round(Math.random() * 0xffffff).toString(16)
                switch (cur.activityType) {
                    case "WALKING":
                        polylineColor = _.get(lineColor, 'WALKING')
                        break
                    case "BUS":
                        polylineColor = _.get(lineColor, 'BUS')
                        break
                    case "SUBWAY":
                        polylineColor = _.get(lineColor, 'SUBWAY')
                        break
                    case "RUNNING":
                        polylineColor = _.get(lineColor, 'RUNNING')
                        break
                    case "ETC":
                        polylineColor = _.get(lineColor, 'ETC')
                        break
                    default:
                        break;
                }
                let polyline = new kakaoAPI.Polyline({
                    map: Map,
                    path: pathPoint,
                    strokeWeight: 6,
                    strokeColor: polylineColor,
                    strokeOpacity: 1,
                    strokeStyle: 'solid',
                    endArrow: true
                })                
                
                kakaoAPI.event.addListener(polyline, 'mouseover', function(mouseEvent) {  
                    polyline.setOptions({
                        strokeWeight: 10,
                        strokeColor: polylineColor,
                        strokeOpacity: 1,
                        strokeStyle: 'solid'
                    })       
                })
                
                kakaoAPI.event.addListener(polyline, 'mouseout', function(mouseEvent) {  
                    polyline.setOptions({
                        strokeWeight: 6,
                        strokeColor: polylineColor,
                        strokeOpacity: 1,
                        strokeStyle: 'solid'
                    })
                })

                kakaoAPI.event.addListener(polyline, 'click', function(mouseEvent) {  
                    setCurPolylineIdx(cur.index)        
                })
                tempPolyline.push(polyline)
            }
        })
        tempPolyline.map((cur) => cur.setMap(Map))
        tempMarker.map((cur) => cur.setMap(Map))
        setPolylineList(tempPolyline)
        setMarkerList(tempMarker)
    }

    return (
        <div>
            <div
                className="map"
                style={{ width: "500px", height: "500px" }}
                ref={container}
            ></div>
        </div>
  )
}

export default Map


/*
Color 조합 참고 표 - https://www.webdesignrankings.com/resources/lolcolors/
https://gifguide2code.com/2018/02/12/json-how-to-read-your-google-location-data/

*/
profile
기록 열심히하는 개발자인척
post-custom-banner

0개의 댓글