متاسفانه گوگل مدتی است که برای سرویس Google Map که مدتها کاملا رایگان سرویسدهی میکرد ، تعرفه تعیین کرده که با وجود تعرفه پایین ، استفاده از آن را برای ما بسیار سخت و تقریبا غیر ممکن کرده است. اما با این حال خوشبختانه هنوز جایگزینهای رایگانی وجود دارد که ما بتونیم به پروژهها:
اگه این موارد نیازهای پروژتون است بریم برای پیاده سازی.
نکته: پلتفرم MapBox که ما از آن هم استفاده میکنیم کاملا رایگان نیست و محدودیت load در ماه داره ولی تعداد load خیلی زیاده توی ماه میده که برای خیلی از پروژهها کافیه اما با این حال ، جایگزین کاملا رایگان هم داره (Open Street Map) که توی قسمت پیاده سازی اون هم کاملا توضیح می دهم.
ساختاری که قصد پیادهسازی اون داریم شامل دو بخش اصلی است:
1. کتابخانه react-map-gl:
قالب اصلی نقشه با این کتابخانه پیاده سازی میشه. در واقع ما با اضافه کردن این کتابخانه و استفاده از آن میتوانیم:
الف. قالبی که میخواهیم نقشه بر روی آن نمایش داده شود را پیادهسازی کنیم. برای مثال frame ای با سایزهای width: 100% و Height: 200px.
ب. نقاطی که میخوایم بر روی نقشه نمایش دهیم را با لیستی از مختصات هر نقطه نمایش دهیم.
پ. اطلاعات هر نقطه را نیز با استفاده از همین کتابخانه روی نقشه قرار دهیم.
2. پلتفرم نمایش نقشه MapBox
بعد از پیاده سازی قالب نقشه ، حالا نیاز داریم نقشهای را روی آن قالب به نمایش بذاریم. یکی از این پلتفرمها MapBox. در واقع این پلتفرمها ، API هستند که به کتابخانه react-map-gl سرویس میدهند و تصاویر هر بخش از نقشه را که این کتابخانه نیاز داشته باشد برای آن آماده میکند.
اول کتابخانه react-map-gl را به پروژه اضافه میکنیم:
npm install --save react-map-gl
حالا باید به component که قصد داریم در آن نقشه اضافه کنیم ، کتابخانه را import کنیم:
import ReactMapGL, {Marker, Popup} from "react-map-gl"
در این import سه ایتم اضافه کردیم. ReactMapGL تگ اصلی برای قالب نمایشی نقشه است. تمامی تنظیمات قالب ، داخل این تگ صورت میگیره. Marker هم برای نشانه گذاری نقاط روی نقشه استفاده میشه و Popup برای نمایش اطلاعات آن نقطهها. البته اگر نیازی به نشانهگذاری روی نقشه ندارید میتونید از این دو استفاده نکنید.
قبل اضافه کردن تگ اصلی یعنی ReactMapGL ، اول نیاز به سه state داریم. دو state برای نگهداشتن مختصات (latitude و longitude) محل نمایش فعلی نقشه و یک state برای نگهداری میزان zoom بر روی نقشه:
const [latitude, setLatitude] = useState(35.6892) const [longitude, setLongitude] = useState(51.3890) const [zoom, setZoom] = useState(10)
حالا با استفاده از تگ اصلی ReactMapGL بدنه اصلی نقشه را پیاده میکنیم. بعد از این مرحله عملا ما یک Map کامل داریم:
<ReactMapGL width="100%" height={400} latitude={latitude} longitude={longitude} zoom={zoom} mapStyle='mapbox://styles/mapbox/streets-v11' mapboxApiAccessToken="YourToken" onViewportChange={(viewState) => { setLatitude(viewState.latitude); setLongitude(viewState.longitude); setZoom(viewState.zoom) }}> </ReactMapGL>
فقط در مورد props های mapStyle و mapboxApiAccessToken نیاز است اول در سایت MapBox حساب کاربری باز کنید و پروژه خودتون داخلش تعریف کنید. پنل به ازای هر پروژه به شما یک AccessToken میده که به شما اجازه میدهد به تعداد محدود اما واقعا زیادی در ماه نقشه را load کنید. اما اگه نیاز داشتید که این محدودیت هم نداشته باشید میتونید به جای MapBox از پلتفرم کاملا رایگان OSM استفاده کنید که برای این کار لازمه mapStyle به مقدار زیر تغییر دهید:
https://s3.amazonaws.com/cdn.brianbancroft.io/assets/osmstyle.json
نکته: در صورت استفاده از OSM دیگر نیاز به props برای توکن (mapboxApiAccessToken) نیست و لازم نیست حساب کاربری در MapBox داشته باشید.
نکته: از سه state که در component خودمون اضافه کردیم ، همگی را داخل تگ بالا استفاده کردیم. props های latitude و longitude و zoom با مقدار لحظهای که دارند ، یک بخش از نقشه را نمایش میدهند. با onViewportChange هم ، هر بار که کاربر تغییری در نقشه ایجاد کند ، مقدار دقیق تغییرات را به ما بر میگرداند و ما باید state های خودمون با این مقادیر جدید بروزرسانی کنیم. (ادامه توضیح کد بالا بود و نیازی به تغییر کد نیست)
با همین تگ حالا ما یک نقشه کامل روی پروژه پیاده سازی کردیم:
حالا اگه بخوایم روی نقشه نقاطی رو نشانهگذاری کنیم ، کافیه داخل بدنه تگ ReactMapGL ، نقاط را به شکل زیر تعریف کنیم:
<Marker latitude={35.6892} longitude={51.3890}> <img className="Marker" src={logo} alt=""/> </Marker> <Popup className="Popup" latitude={35.6892} longitude={51.3890} closeButton={false} closeOnClick={false} tipSize={10}>فروشگاه</Popup>
با قرار دادن این تکه کد عملا یک نقطه را روی نقشه تعریف کردیم و به همین شکل میتوانیم تعداد نقاط بیشتری را نیز تعریف کنیم:
برای اصلاح این مشکل لازمه در App.js پلاگین زیر را اضافه کنیم که تنها یکبار فراخوانی بشه:
ابتدا نصب mapbox-gl:
npm install --save mapbox-gl
حالا در App.js :
import {setRTLTextPlugin} from "mapbox-gl";
setRTLTextPlugin( 'https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-rtl-text/v0.2.3/mapbox-gl-rtl-text.js', () => {}, true );
امیدوارم تونسته باشم کمکی کرده باشم.