پیاده سازی svg introduction در react-native

خب تقریبا به کارهای پایانی توسعه محصول رسیدین و همه چی ایشالا مثل ساعت داره دقیق کار میکنه (هر چی باگ هم هست مال تیم قبلیه) و با ui دلبرانه دارین آماده میشین که مارکت رو تصاحب کنید. اما ممکنه امکانات اپ شما برای ورژن اول زیاد شده باشه و در دموی اول میبینین که به کاربراتون دارین از اون اول توضیح میدین که چیکار کنند و این کمی نگرانتون می کنه. یا اصلا نگران این هستین مخاطب ندونه از کجا باید شروع کنه و هر اصطلاح داخل اپ شما چه معنی میده.یکی از کارهایی که میشه انجام داد اینه که برای screen های مورد نظر برنامه تون intro بذارین. این کار رو هم میتونین به شکل اسلایدر های توضیحی توام با عکس انجام بدین (که احتمالا نمونه اش رو زیاد دیدین) و هم اینکه روی اسکرین اپ دکمه ها رو هایلایت کنین و به کاربر بگین با زدن این دکمه چنین کاری رو میتونه انجام بده. ما هم از این قاعده مستثنی نبودیم و یکی از چالش های جالبی که برای اپلیکیشن ejob داشتیم پیاده سازی همین introduction بود که قسمت هایی از اون رو در عکس زیر می بینید. در این مقاله میخوایم یاد بگیریم چطوری چیزی شبیه به این عکس بسازیم. سعی کردم نکات مهمی رو که خودم باهاشون سر و کله زدم رو به صورت خلاصه بنویسم.نتیجه همین کار که برای اپلیکیشن ایجاب انجام دادمتعریف پروژه و نصب پکیج های مورد نیاز:یه پروژه react-native تعریف می کنیم.npx react-native init introductionنیاز داریم با svg هم کار کنیم:yarn add react-native-svgیه اسکرین داریم که به شکل زیر هستش:صفحه ای که در نظر داریم براش آموزش بذاریم. خب این صفحه رو من داخل app.js ساختم که یه همچین کدی داره:کد صفحه appساختن کامپوننت Introduction:خب تا اینجای کار یه اسکرین تست درست کردیم و حالا میخوایم به کاربر توضیح بدیم هر کدوم از دکمه ها چه کار میکنه. فرض کنید برای دکمه های filter و post میخوایم یه intro بسازیم. یه کامپوننت میسازم به نام Introduction که شامل یه Modal خواهد بود که المنت های ما رو به شکل هایلایت معرفی میکنه.کد کامپوننت Introductionخب ما دو تا props برای این کامپوننت داریم:اولی elements هست که یک array از object ها هست که جلوتر میبینید که شامل چه property هایی هستند. دومی dismiss هست که یک فانکشنی هست برای بستن نمایش intro که از کامپوننت والد بهش میفرستیم.نکته مهم که حتما modal باید transparent باشه.یه state به نام current دارم که ازش برای مشخص کردن المنت فعلی که نمایش میده استفاده می کنم. یه دکمه داریم که منطق onPress اون به این شکل هست: اگه المنت فعلی آخرین المنت باشه از آرایه elements باید modal بسته بشه، در غیر این صورت یدونه به مقدار current اضافه میکنم تا بره به المنت بعدی.در رابطه با تگ های svg بخوام توضیح بدم این پست طولانی میشه و به همین دلیل فقط چند نکته مهم راجع بهش میگم. تگ defs به صورت مستقیم render نمیشه، تگ های svg که داخلش تعریف کنین نگه میداره و بعدا میتونین با رفرنس دادن بهشون ازشون استفاده کنید. تگ mask هم برای ترکیب آبجکتی که میخوایم با بک گراند لازم داریم. تگ ماسک داخلش دو تا تگ rect تعریف شده که یکی با fill سفید و اون یکی سیاه هست. کار fill سفید این هست که بک گراند ما رو که اینجا همون LinearGradient هست رو به خودش بگیره و fill سیاه اون بخش از بک گراند رو تو خالی نمایش میده. (شبیه همون چیزی که توی فتوشاپ هم داریم.)اما سوال اینجاست که اندازه اون المنت ها و محل نمایششون در صفحه رو از کجا بیاریم؟ برگردیم توی کامپوننت اپ و اون هم ببینیم.محاسبه موقعیت المنت های مد نظر در صفحه:کامپوننت اپ رو یه سری تغییرات انجام میدیم و کد نهاییمون به شکل زیر خواهد بود. دو تا state داریم. items آبجکتی از مقادیر اندازه ی المنت های مورد نظر و showIntro که برای شرط نمایش Introduction از اون استفاده می کنم.نکته: در مواقعی که رندر کردن کامپوننت Introduction بدون شرط باشه ممکنه اپ شما کرش کنه. چون رندر انجام شده اما مقادیر داخل تگ های svg شامل محل قرارگیری المنت به svg نرسیده. پس بهتره همیشه این موضوع رو به هر شکلی که راحتین کنترلش کنید.برای به دست آورن محل قرارگیری المنت مد نظر، UIManager و findNodeHandler رو از react-native ایمپورت می کنیم. متد measure رو فراخوانی می کنیم و findeNodeHandler را با ورودی ref المنت مورد نظر و همچنین یه callback به متد measure پاس میدهیم.همچنان برای خلاصه نوشتن این قسمت میتونین فانکشن onLayout را به این صورت نیز بنویسید:onLayout={() => { postRef.current.measure((x, y, width, height, pageX, pageY) => { setItems(prevState => ({ ...prevState, post: { x, y, width, height, pageX, pageY } })); })بعد از به دست آوردن مقادیر مد نظر حالا وقتشه که کامپوننت Introduction رو رندر کنیم. داخل هوک useEffect که به items وابسته است شرطی گذاشتم که اگه طول items برابر با 2 بود (یعنی مقدار موقعیت هر دو المنت در صفحه محاسبه شده است)، وضعیت showIntro تغییر کند.خب همه چی سر جاش قرار داره و میریم اپ رو refresh میکنم. نتیجه نهایی به شکل زیر است: نتیجه نهاییامیدوارم که این آموزش داخل پروژه هاتون به کار بیاد و تونسته باشه گره ای از مشکلاتتون رو باز کنه. شاید دوستانی هم داشته باشید که دنبال چنین راه حلی باشند، لطفا به اون ها هم معرفی کنید. سوالی هم اگه داشتین میتونین در کامنت بپرسین، سعی میکنم در زودترین زمان ممکن جواب بدم.