ساخت اپلیکیشن کرونا با React – از صفر تا صد


در این مقاله با روش ساخت اپلیکیشن کرونا با React و طراحی نقشه انتشار ویروس و داشبورد مربوطه با بهرهگیری از Gatsby و Leaflet آشنا خواهیم شد.
آغاز کار با Leaflet
ما قصد داریم اپلیکیشنی ایجاد کنیم که از یک API شامل آمار لحظهای مواجه کشور با کرونا بهره میگیرد. این اپلیکیشن نقشه، یک نشانگر برای هر کشور نمایش میدهد که تعداد کیسهای تأیید شده را نشان میدهد. سپس یک tooltip کوچک را قرار میدهیم که جزییات اطلاعات را نمایش دهد. ما از tileserver عمومی OpenStreetMap استفاده میکنیم. برای شروع به کار باید از دستورهای زیر پیروی کنید:
- دستور node یا yarn
- CLI گتسبی به صورت yarn global add gatsby-cli
ابتدا باید یک مبنا برای نقشه ایجاد کنیم. این کار را با استفاده از استارتر Leaflet Gatsby با ریاکت میتوانیم انجام دهیم.
gatsby new my-coronavirus-map https://github.com/colbyfayock/gatsby-starter-leaflet
سپس به محل پروژه میرویم و سرور توسعه را آغاز میکنیم.
cd my-coronavirus-map yarn develop
اکنون میتوانیم نقشه ابتدایی را در مرورگر ببینیم.
به طور کلی این نقشه دارای یک اسپینر است که برای سهولت بیشتر باید برخی کدهای آن را پاک کنیم. فایل src/pages/index صفحه اصلی این اپلیکیشن است. هر چیزی که درون تابع mapEffect قرار دارد را پاک کنید.
async function mapEffect({ leafletElement } = {}) { }
سپس نام متغیرمان که LeafletElement است را برای درک بهتر عوض میکنیم.
async function mapEffect({ leafletElement: map } = {}) { }
اکنون دیگر نیازی به نشانگر نداریم. بنابراین کامپوننت Marker را از کامپوننت Map حذف میکنیم.
<Map {...mapSettings} />
ما باید همه ایمپورتهای زیر و متغیرها را از فایل حذف کنیم:
- useRef
- Marker
- promiseToFlyTo
- getCurrentLocation
- gatsby_astronaut
- timeToZoom
- timeToOpenPopupAfterZoom
- timeToUpdatePopupAfterZoom
- ZOOM
- popupContentHello
- popupContentGatsby
- markerRef
اکنون نگاهی به نقشه خودمان میاندازیم.
واکشی دادههای API
در این اپلیکیشن باید از NOVELCOVID API استفاده کنیم. به طور خاص قصد داریم از نقطه انتهایی کشورها (countries) برای واکشی لیستی از همه آمارهای کشورها استفاده کنیم.
برای ایجاد درخواستها از axios کمک میگیریم. این یک API زیبا است که هر جایی میتوانید استفاده کنید. اگر میخواهید از fetch یا کتابخانه خاص خود برای درخواستها استفاده کنید، باید آن را در پروژه خود پیادهسازی کنید.
کد زیر را برای اجرای نصب axios اجرا کنید:
yarn add axios
زمانی که نصب شد، دوباره سرور را ریاستارت کنید. پکیج axios را در فایل pages/index.js ایمپورت کنید:
import axios from 'axios';
اکنون درون تابع mapEffect یک درخواست به نقطه انتهایی API ارائه میکنیم.
1async function mapEffect({ leafletElement: map } = {}) {
2 let response;
3
4 try {
5 response = await axios.get('https://corona.lmao.ninja/v2/countries');
6 } catch(e) {
7 console.log(`Failed to fetch countries: ${e.message}`, e);
8 return;
9 }
10
11 const { data = [] } = response;
12}
اکنون اگر به لاگ کنسول سر بزنید، شیء data را میبینید که دادهها را به صورت موفقی واکشی کرده است.
تبدیل دادهها به فرمت دادههای جغرافیایی
اینک که دادهها را در اختیار داریم، باید آن را به فرمت دادههای جغرافیایی و به طور خاص فرمت GeoJSON تبدیل کنیم.
کار خود را با افزودن این کد به پروژه آغاز میکنیم.
1const { data = [] } = response;
2const hasData = Array.isArray(data) && data.length > 0;
3
4if ( !hasData ) return;
5
6const geoJson = {
7 type: 'FeatureCollection',
8 features: data.map((country = {}) => {
9 const { countryInfo = {} } = country;
10 const { lat, long: lng } = countryInfo;
11 return {
12 type: 'Feature',
13 properties: {
14 ...country,
15 },
16 geometry: {
17 type: 'Point',
18 coordinates: [ lng, lat ]
19 }
20 }
21 })
22}
- در کد فوق ابتدا یک ثابت جدید به نام hasData ایجاد کردهایم که برای بررسی این نکته استفاده میشود که آیا متغیر data یک آرایه است و آیا داده دارد یا نه. اگر دادهای نداشته باشیم، باید آن را به تابع بازگشت دهیم، زیرا نمیخواهیم دادههایی را که نداریم اضافه کنیم.
- ما یک شیء ایجاد کردهایم که سند GeoJSON ما محسوب میشود.
- سندی که ما استفاده میکنیم از نوع FeatureCollection است و از این رو روی دیتاست خود حلقهای تعریف میکنیم.
- برای هر کشور، دادهها را به شکل lat و lng به دست میآوریم تا یک نقطه روی نقشه تشکیل دهیم.
اکنون سند GeoJSON را به پروژه خود اضافه میکنیم. ظاهر آن در console.log و geojson.io به صورت زیر است:
افزودن دادهها به نقشه
اکنون که سند GeoJSON را داریم، آن را به نقشه اضافه میکنیم.
1const geoJsonLayers = new L.GeoJSON(geoJson, {
2 pointToLayer: (feature = {}, latlng) => {
3 const { properties = {} } = feature;
4 let updatedFormatted;
5 let casesString;
6
7 const {
8 country,
9 updated,
10 cases,
11 deaths,
12 recovered
13 } = properties
14
15 casesString = `${cases}`;
16
17 if ( cases > 1000 ) {
18 casesString = `${casesString.slice(0, -3)}k+`
19 }
20
21 if ( updated ) {
22 updatedFormatted = new Date(updated).toLocaleString();
23 }
24
25 const html = `
26 <span class="icon-marker">
27 <span class="icon-marker-tooltip">
28 <h2>${country}</h2>
29 <ul>
30 <li><strong>Confirmed:</strong> ${cases}</li>
31 <li><strong>Deaths:</strong> ${deaths}</li>
32 <li><strong>Recovered:</strong> ${recovered}</li>
33 <li><strong>Last Update:</strong> ${updatedFormatted}</li>
34 </ul>
35 </span>
36 ${ casesString }
37 </span>
38 `;
39
40 return L.marker( latlng, {
41 icon: L.divIcon({
42 className: 'icon',
43 html
44 }),
45 riseOnHover: true
46 });
47 }
48});
- در کد فوق یک وهله جدید از L.GeoJSON ایجاد کردیم که سند GeoJSON را به Leaflet تبدیل میکند.
- pointToLayer سفارشی درون وهله تعریف شده است و به ما امکان خواهد داد که لایه نقشه را که Leaflet در نقشه ما ایجاد کرده است سفارشیسازی کنیم.
- L.marker با پیکربندی سفارشی ما بازگشت مییابد که شامل یک کلاس از آیکون برای کانتینر و HTML سفارشی است.
ما باید یک کد CSS به فایل assets/stylesheets/components/_map.scss خود اضافه کنیم تا آن را تعاملیتر کنیم:
1.icon-marker {
2
3 display: flex;
4 position: relative;
5 justify-content: center;
6 align-items: center;
7 color: white;
8 width: 3.6em;
9 height: 3.6em;
10 font-size: .7em;
11 font-weight: bold;
12 background-color: $red-800;
13 border-radius: 100%;
14 box-shadow: 0 2px 5px rgba(black, .9);
15
16 &:hover {
17
18 .icon-marker-tooltip {
19 display: block;
20 }
21
22 }
23
24}
25
26.icon-marker-tooltip {
27
28 display: none;
29 position: absolute;
30 bottom: 100%;
31 width: 16em;
32 font-size: 1.4em;
33 padding: 1em;
34 background-color: $blue-grey-900;
35 border-radius: .4em;
36 margin-bottom: 1em;
37 box-shadow: 0 3px 5px rgba(black, .9);
38
39 &:before {
40 display: block;
41 position: absolute;
42 bottom: -.6em;
43 left: 50%;
44 content: '';
45 width: 1.4em;
46 height: 1.4em;
47 background-color: $blue-grey-900;
48 transform: rotate(45deg);
49 margin-left: -.7em;
50 }
51
52 h2 {
53 font-size: 1.5em;
54 line-height: 1.2;
55 margin-bottom: .1em;
56 margin-top: 0;
57 }
58
59 h3 {
60 font-size: 1.2em;
61 margin: .1em 0;
62 font-weight: normal;
63 color: $blue-grey-100;
64 }
65
66 ul,
67 p {
68 font-weight: normal;
69 }
70
71 ul {
72 list-style: none;
73 padding: 0;
74 margin: .6em 0 0;
75 }
76
77}
اکنون لایه geoJson خود را ایجاد کردهایم و آن را به اپلیکیشن اضافه میکنیم.
geoJsonLayers.addTo(map)
این نقشه به صورت خودکار روی مرکز تنظیم نمیشود. همواره باید مطمئن شوید که کد زیر را درون index.js اضافه کردهاید تا در مرکز قرار گیرد:
1const LOCATION = {
2 lat: 0,
3 lng: 0
4};
اینک میتوانیم ظاهر اپلیکیشن نهایی خود را ببینیم:
سخن پایانی
در این مقاله با روش ساخت اپلیکیشن کرونا با React آشنا شدیم.
این اپلیکیشن آماری در مورد کیسهای بیماری کووید-19 در سراسر دنیا ارائه میکند. شما میتوانید استایلها و کارکردهای دیگری هم به این اپلیکیشن اضافه کنید. امیدواریم این راهنما مورد توجه شما قرار گرفته باشد.