Completed Map_20210430_Day3

2021. 5. 1. 00:57·Projects/Covid19 Tracker_2021

[ADD]Make Covid19 Map function

- Utilize Leaflet Service for making Map

- Circles for Covid19 / Recovered / Deaths

- Detect location of country and zoom-in

- Click Effects on infoboxes by CSS


 

맵 구현

 

1) useEffect in App.js, 모든 국가의 바이러스 관련 데이터를 fetch 해온다

await fetch("https://disease.sh/v3/covid-19/countries")

2) setMapCountries 의 상태로 데이터 저장

3) 상태값 mapCenter, mapZoom, mapCountries, casesType 을 Map 컴포넌트에 전달

 

App.js

import React, { useState, useEffect } from 'react'
import './App.css';
import {
  MenuItem,
  FormControl,
  Select,
  Card,
  CardContent
} from "@material-ui/core"
import InfoBox from './Infobox'
import Map from './Map'
import Table from './Table'
import LineGraph from './LineGraph'
import { sortData, prettyPrintStat } from './util'
import 'leaflet/dist/leaflet.css'

function App() {

  ...생략...
  
  const [mapCenter, setMapCenter] = useState({ lat: 37, lng: 127.5});
  const [mapZoom, setMapZoom] = useState(3);
  const [mapCountries, setMapCountries] = useState([]);
  const [casesType, setCasesType] = useState("cases");

...생략...

  useEffect(() => {
    const getCountriesData = async () => {
      await fetch("https://disease.sh/v3/covid-19/countries")
      .then(res => res.json())
      .then((data) =>{
        const countries = data.map((country)=> (
          {
            name:country.country,
            value: country.countryInfo.iso2
          }
        ))
        // console.log(data)
        const sortedData = sortData(data);
        setTableData(sortedData);
        setMapCountries(data);
        setContries(countries);
        // console.log(countries)
      })
    }
    getCountriesData();
  }, [])

...생략...

  return (
    <div className="app">
      <div className="app__left">
      
...생략...

        <Map countries={mapCountries} casesType={casesType} center={mapCenter} zoom={mapZoom}/>
      </div>
       
...생략...       
       
    </div>
  );
}

export default App;

 

4) react-leaflet 라이브러리의 해당 엘리먼트에 각 상태(mapCenter, mapZoom, mapCountries, casesType)를 전달

      <MapContainer>
        <ChangeView center={center} zoom={zoom}/>
        <TileLayer
        url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
        attribution='&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
        />
        {showDataOnMap(countries, casesType)}
      </MapContainer>

 

Map.js

import React from 'react';
import { MapContainer, TileLayer, Marker, Popup, useMap } from 'react-leaflet';
import './Map.css';
import { showDataOnMap } from './util';

function Map({countries, casesType, center, zoom}) {

  function ChangeView({ center, zoom }) {
    const map = useMap();
    map.setView(center, zoom);
    return null;
  }

  // console.log(countries.country)
  // console.log(casesType)
  // console.log(typeof casesType)

  return (
    <div className="map">
      <MapContainer>
        <ChangeView center={center} zoom={zoom}/>
        <TileLayer
        url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
        attribution='&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
        />
        {showDataOnMap(countries, casesType)}
      </MapContainer>
    </div>
  )
}

export default Map

5) showDataOnMap 컴포넌트에서 data 와 casesType 을 받아,

  a. Circle 엘리먼트의 center(국가의 위도와 경도)를 추출 및 반영

  b. casesTypeColors 를 이용하여 casesType 에 따라 radius(반경) 산출, pathOptions 에서 다른 색 적용

  c. Popup 엘리먼트에 국기 이미지, cases, recovered, deaths 수를 반영

country data

6) 렌더링

 

util.js - showDataOnMap

import React from 'react';
import { Circle, Popup } from 'react-leaflet';
import numeral from 'numeral';

const casesTypeColors = {
  cases: {
    hex: "#CC1034",
    rgb: "rgb(204, 16, 52)",
    half_op: "rgba(204, 16, 52, 0.5)",
    multiplier: 400,
  },
  recovered: {
    hex: "#7DD71D",
    rgb: "rgb(125, 215, 29)",
    half_op: "rgba(125, 215, 29, 0.5)",
    multiplier: 500,
  },
  deaths: {
    hex: "#fb4443",
    rgb: "rgb(251, 68, 67)",
    half_op: "rgba(251, 68, 67, 0.5)",
    multiplier: 1000,
  },
};

...생략...

//Draw circles on the map with interative tooltip
export const showDataOnMap = (data, casesType) =>(
  data.map(country => (
    <Circle
    center={[country.countryInfo.lat, country.countryInfo.long]}
    fillOpacity={0.4}
    pathOptions={{
      color:casesTypeColors[casesType].hex,
      fillColor: casesTypeColors[casesType].hex
    }}
    radius={
      Math.sqrt(country[casesType]) * casesTypeColors[casesType].multiplier
    }
    >
    <Popup style={{display:"flex", backgroundColor:"gray"}}>
      <div className="info-container">
        <div className="info-flag">
          <img src={`${country.countryInfo.flag}`} alt=""/>
        </div>
        <div className="info-confirmed">Cases: {numeral(country.cases).format("0,0")}</div>
        <div className="info-recovered">Recovered: {numeral(country.recovered).format("0,0")}</div>
        <div className="info-deaths">Deaths: {numeral(country.deaths).format("0,0")}</div>
        <div></div>
      </div>
    </Popup>

    </Circle>
  ))
)

추가 진행 예정

- 코드 로직 리뷰 및 적용 라이브러리 사용법 정리

- CSS refactoring

 

도움 받은 사이트

  • React leaflet center attribute does not change when the center state changes
    • stackoverflow.com/questions/64665827/react-leaflet-center-attribute-does-not-change-when-the-center-state-changes/64667351#64667351
  • leafletjs.com/react-leaflet.js.org/docs/start-installation
  • install leaflet: github.com/PaulLeCam/react-leaflet/issues/491

'Projects > Covid19 Tracker_2021' 카테고리의 다른 글

Category/Data table/Basic Map_20210429_Day2  (0) 2021.04.30
Initial Set up & Covid19 API_20210428 _Day1  (0) 2021.04.29
'Projects/Covid19 Tracker_2021' 카테고리의 다른 글
  • Category/Data table/Basic Map_20210429_Day2
  • Initial Set up & Covid19 API_20210428 _Day1
JTB
JTB
웹/앱 개발 정보를 공유하고 있습니다.
  • JTB
    JTechBlog
    JTB
  • 전체
    오늘
    어제
    • All About Programming;) N
      • Computer Science
        • Terminology and Concepts
        • Network
        • Operating System
        • Database
        • Data Structure
      • Frontend
        • Javascript Essentials
        • Perfomance Optimization
        • JS Patterns
        • Next.js
        • Flutter
      • Backend
        • Node.js
      • DevOps
        • Docker & Kubernetes
      • Coding Test N
        • LeetCode N
        • Programmers
      • Tech Books & Lectures
        • Javascript_Modern JS Deep d..
        • Network_IT 엔지니어를 위한 네트워크 입문
      • Projects
        • PolyLingo_2025
        • Build Your Body_2024
        • JStargram_2021
        • Covid19 Tracker_2021
        • JPortfolio_2021
      • BootCamp_Codestates
        • TIL
        • TILookCloser
        • Pre Tech Blog
        • IM Tech Blog
        • Daily Issues and DeBugging
        • First Project
        • Final Project
        • Sprint Review
        • Good to Know
        • Socrative Review
        • HTML &amp; CSS
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

    • 글쓰기
    • 관리
  • 공지사항

  • 인기 글

  • 태그

    DOM
    Binary Tree BFS
    database
    testing
    polylingo
    자바스크립트
    커리어
    How memory manage data
    이벤트
    프론트엔드 성능 최적화 가이드
    mobile app
    Time complexity and Space complexity
    js pattern
    structure of os
    스코프
    indie hacker
    딥다이브
    모던 자바스크립트 Deep Dive
    Network
    JavaScript
    CPU scheduling algorithm
    자바스크립트 딥다이브
    need a database
    Shared resources
    TCP/IP
    Data Structure
    Threads and Multithreading
    Operating System
    leetcode
    VoiceJournal
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.5
JTB
Completed Map_20210430_Day3
상단으로

티스토리툴바