متن خبر

نحوه ساخت یک کامپوننت سوایپ موبایل در React

نحوه ساخت یک کامپوننت سوایپ موبایل در React

شناسهٔ خبر: 447669 -




این روزها همه دوست دارند که بتوانند از طریق تلفن همراه خود به وب دسترسی داشته باشند. پس مهم است که دسترسی به برنامه وب خود را در اندروید و آیفون در نظر بگیرید.

سخت‌ترین بخش ساخت ناوبری است – و به‌ویژه کشیدن انگشت می‌تواند باعث سردردهای زیادی شود. کتابخانه‌هایی وجود دارد که می‌توانید از آنها برای کمک به این موضوع استفاده کنید، اما چرا خودتان آن را ایجاد نکنید؟

در این آموزش به شما یاد می دهم که چگونه در React کامپوننت کشیدن موبایل خود را بسازید. می توانید آن را در 50 خط جاوا اسکریپت انجام دهید.

در ابتدا، من این کامپوننت را برای پروژه حیوان خانگی خود، بازی 2048 در React ایجاد کردم و اکنون تصمیم گرفتم نحوه انجام آن را به اشتراک بگذارم.

اگر می‌خواهید قبل از خواندن کل مقاله آن را امتحان کنید، می‌توانید بازی را در اینجا انجام دهید (از دستگاه تلفن همراه خود استفاده کنید). در این آموزش، ما فقط بر روی کشیدن گوشی موبایل تمرکز خواهیم کرد.

می توانید منابع زیر را در GitHub بیابید:

📱 کد منبع کامپوننت

🕹️ کد منبع بازی 2048

در اینجا اوج پنهانی است (کیفیت بهترین نیست زیرا سعی می کردم اندازه را کوچک نگه دارم):

MobilePreview-low--1-
نتیجه نهایی در پروژه حیوان خانگی من

فهرست مطالب:

    پیش نیازها

    چگونه یک دستگاه موبایل را در مرورگر خود شبیه سازی کنیم

    مؤلفه Mobile Swiper

    بیایید آن را قابل کشیدن (Swipable) کنیم

    خلاصه

🛠️ پیش نیازهای P

قبل از شروع، مطمئن شوید که کمی در مورد React و جاوا اسکریپت می دانید. شما به هیچ ابزار پیچیده ای نیاز ندارید، اما اگر می خواهید نمونه پروژه را روی رایانه خود اجرا کنید، ابتدا باید Node.js را نصب کنید.

همچنین، من از Google Chrome برای شبیه سازی یک دستگاه تلفن همراه در رایانه خود استفاده می کنم. به خاطر داشته باشید که اگر از مرورگر دیگری استفاده می کنید، ممکن است مراحل کمی متفاوت باشد.

🔍 چگونه یک دستگاه موبایل را در مرورگر خود شبیه سازی کنیم

قبل از شروع کدنویسی، باید به شما نشان دهم که چگونه یک دستگاه تلفن همراه را در Google Chrome شبیه سازی کنید.

مرورگر خود را باز کنید، روی صفحه خود کلیک راست کرده و از منوی کشویی " Inspect " را انتخاب کنید.

MobileSwiper-1
نحوه باز کردن Developer Tools در گوگل کروم

نمای مرورگر شما اکنون باید به دو قسمت تقسیم شود. بخش دوم شامل ابزارهای توسعه دهنده کروم است.

اکنون روی نماد "لپ تاپ و موبایل" (1 در تصویر زیر) در گوشه سمت چپ بالای ابزار Developer کلیک کنید. سپس "Dimensions" (2) دستگاهی را که می خواهید شبیه سازی کنید انتخاب کنید. من آیفون SE را انتخاب کردم زیرا این دستگاه دارای کمترین وضوح پشتیبانی شده توسط بازی من است.

MobileSwiper-2
انتخاب ابعاد دستگاه در Developer Tools (Google Chrome)

اکنون ما آماده ایم تا با استفاده از موس یا پد لمسی، کشیدن کشیدن انگشت را شبیه سازی کنیم. فقط به GIF زیر توجه کنید - مکان نما من به یک دایره تبدیل شده است که قرار است ناحیه پوشانده شده توسط انگشت شخص را تجسم کند.

وقتی می‌خواهم تند بکشم، مرورگرم فکر می‌کند که در واقع در وب‌سایت پیمایش می‌کنم. در مورد من، این یک رفتار مورد انتظار نیست. من می خواهم به جای آن از کشیدن انگشت برای انجام بازی استفاده کنم.

بازی-v2-شکسته شده
به طور پیش‌فرض، رویدادهای پیمایش با تند کشیدن همراه هستند

🤓 جزء MobileSwiper

ابتدا باید یک swiper برای موبایل ایجاد کنیم . فایل jsx در این فایل یک کامپوننت استاندارد React را اعلام می کنیم. مؤلفه ما باید دو ویژگی را بپذیرد - children و onSwipe .

 export default function MobileSwiper({ children, onSwipe }) { return null }

بگذارید به طور مختصر در مورد آنها توضیح دهم:

children به MobileSwiper اجازه می‌دهد تا هر محتوایی را که بین تگ‌های باز و بسته شدن آن قرار می‌گیرد، بپذیرد و ارائه دهد. این به شما امکان می دهد کل برد را در داخل این جزء تزریق کنید - اما بعداً به این موضوع خواهیم رسید.

onSwipe یک تماس برگشتی است که هر بار که کاربر در ناحیه «قابل کشیدن» تند بکشد، مؤلفه ما فعال می‌شود.

بیایید اکنون منطقه قابل کشیدن را تعریف کنیم. ابتدا باید یک مرجع به عنصر DOM اضافه کنید که می‌خواهید در آن اجازه بکشید. با استفاده از قلاب useRef می توانید این کار را انجام دهید. پس یک ثابت به نام wrapperRef را اعلام کنید:

 import { useRef } from "react" export default function MobileSwiper({ children, onSwipe }) { const wrapperRef = useRef(null) return null }

نکته جانبی: useRef یک React Hook است که به شما امکان می‌دهد به مقداری اشاره کنید که برای رندر کردن لازم نیست. استفاده از آن برای دستکاری DOM بسیار رایج است. React پشتیبانی داخلی برای این دارد.

اکنون فقط باید <div /> را برگردانید که به ثابتی که با استفاده از قلاب useRef ایجاد کرده اید ارجاع می دهد.

 import { useRef } from "react" export default function MobileSwiper({ children, onSwipe }) { const wrapperRef = useRef(null) return <div ref={wrapperRef}>{children}</div> }

بیایید یک لحظه فکر کنیم که چگونه می توانیم کشیدن انگشت را تشخیص دهیم. من معتقدم ساده ترین راه مقایسه موقعیت شروع و پایان انگشت کاربر است.

این بدان معناست که باید موقعیت اولیه انگشت کاربر را در حالت ذخیره کنیم. اساسا، ما مختصات x و y را با استفاده از قلاب useState ذخیره می کنیم.

 import { useState, useRef } from "react" export default function MobileSwiper({ children, onSwipe }) { const wrapperRef = useRef(null) const [startX, setStartX] = useState(0) const [startY, setStartY] = useState(0) return <div ref={wrapperRef}>{children}</div> }

اکنون باید دو تماس رویداد ایجاد کنیم:

handleTouchStart موقعیت شروع انگشت کاربر را تنظیم می کند.

handleTouchEnd موقعیت نهایی انگشت کاربر را تنظیم می کند و شیفت (مثلث) را بر اساس نقطه شروع محاسبه می کند.

بیایید با کنترل کننده رویداد handleTouchStart شروع کنیم:

 import { useCallback, useState, useRef } from "react" export default function MobileSwiper({ children, onSwipe }) { const wrapperRef = useRef(null) const [startX, setStartX] = useState(0) const [startY, setStartY] = useState(0) const handleTouchStart = useCallback((e) => { if (!wrapperRef.current.contains(e.target)) { return } e.preventDefault() setStartX(e.touches[0].clientX) setStartY(e.touches[0].clientY) }, []) return <div ref={wrapperRef}>{children}</div> }

اجازه دهید به طور خلاصه توضیح دهم:

    من این راهنما را در قلاب useCallback قرار دادم تا عملکرد آن را در حافظه پنهان ذخیره کنم و بهبود بخشم. اگر این قلاب را نمی‌شناسید، می‌توانید در اسناد رسمی React درباره آن بخوانید.

    دستور if تحلیل می کند که آیا کاربر در حال کشیدن انگشت در ناحیه قابل کشیدن است یا خیر. اگر آنها به خارج از این ناحیه بکشند، ما به اسکرول کردن ادامه خواهیم داد.

    e.preventDefault() رویداد پیمایش پیش‌فرض را غیرفعال می‌کند.

    دو خط آخر مختصات x و y را در حالت ذخیره می کنند.

حال اجازه دهید کنترل کننده رویداد handleTouchEnd را پیاده سازی کنیم:

 import { useCallback, useState, useRef } from "react" export default function MobileSwiper({ children, onSwipe }) { const wrapperRef = useRef(null) const [startX, setStartX] = useState(0) const [startY, setStartY] = useState(0) const handleTouchStart = useCallback((e) => { if (!wrapperRef.current.contains(e.target)) { return } e.preventDefault() setStartX(e.touches[0].clientX) setStartY(e.touches[0].clientY) }, []) const handleTouchEnd = useCallback((e) => { if (!wrapperRef.current.contains(e.target)) { return } e.preventDefault() const endX = e.changedTouches[0].clientX const endY = e.changedTouches[0].clientY const deltaX = endX - startX const deltaY = endY - startY onSwipe({ deltaX, deltaY }) }, [startX, startY, onSwipe]) return <div ref={wrapperRef}>{children}</div> }

همانطور که می بینید، مراحل 1-3 دقیقاً مشابه پاسخ تماس handleTouchStart است. اکنون مختصات x و y نهایی انگشت کاربر را می گیریم و x و y اولیه را از آن کسر می کنیم. به لطف آن می توانیم جابجایی افقی و عمودی انگشت کاربر (دلتا) را محاسبه کنیم.

سپس آن دلتاها را بر روی onSwipe callback ارسال می کنیم. اگر به خاطر داشته باشید، در ابتدا آن را در قطعات کامپوننت اعلام کردیم.

اکنون باید آن تماس ها را به شنونده رویداد متصل کنیم. برای انجام این کار، می توانیم از قلاب useEffect از React استفاده کنیم.

 import { useCallback, useEffect, useState, useRef } from "react" export default function MobileSwiper({ children, onSwipe }) { const wrapperRef = useRef(null) const [startX, setStartX] = useState(0) const [startY, setStartY] = useState(0) const handleTouchStart = useCallback((e) => { if (!wrapperRef.current.contains(e.target)) { return } e.preventDefault() setStartX(e.touches[0].clientX) setStartY(e.touches[0].clientY) }, []) const handleTouchEnd = useCallback( (e) => { if (!wrapperRef.current.contains(e.target)) { return } e.preventDefault() const endX = e.changedTouches[0].clientX const endY = e.changedTouches[0].clientY const deltaX = endX - startX const deltaY = endY - startY onSwipe({ deltaX, deltaY }) }, [startX, startY, onSwipe]) useEffect(() => { window.addEventListener("touchstart", handleTouchStart) window.addEventListener("touchend", handleTouchEnd) return () => { window.removeEventListener("touchstart", handleTouchStart) window.removeEventListener("touchend", handleTouchEnd) } }, [handleTouchStart, handleTouchEnd]) return <div ref={wrapperRef}>{children}</div> }

می توانید اطلاعات بیشتری در مورد قلاب useEffect در اسناد رسمی React بخوانید.

مؤلفه MobileSwiper اکنون آماده است.

🔌 بیایید آن را قابل کشیدن کنیم

آخرین کاری که باید انجام دهیم این است که جزء خود را به برنامه متصل کنیم. همانطور که اشاره کردم، من از این مؤلفه در بازی 2048 خود استفاده خواهم کرد ( کد منبع ). اگر می‌خواهید از آن در جای دیگری استفاده کنید، راهنمای handleSwipe و مؤلفه MobileSwiper یکسان باقی می‌مانند.

بیایید آن را به مؤلفه Board وصل کنیم:

 import { useCallback, useContext, useEffect, useRef } from "react" import { Tile as TileModel } from "@/models/tile" import styles from "@/styles/board.module.css" import Tile from "./tile" import { GameContext } from "@/context/game-context" import MobileSwiper from "./mobile-swiper" export default function Board() { const { getTiles, moveTiles, startGame } = useContext(GameContext); // ... removed irrelevant parts ... const handleSwipe = useCallback(({ deltaX, deltaY }) => { if (Math.abs(deltaX) > Math.abs(deltaY)) { if (deltaX > 0) { moveTiles("move_right") } else { moveTiles("move_left") } } else { if (deltaY > 0) { moveTiles("move_down") } else { moveTiles("move_up") } } }, [moveTiles]) // ... removed irrelevant parts ... return ( <MobileSwiper onSwipe={handleSwipe}> <div className={styles.board}> <div className={styles.tiles}>{renderTiles()}</div> <div className={styles.grid}>{renderGrid()}</div> </div> </MobileSwiper> ) }

بیایید با handleSwipe handler شروع کنیم. همانطور که می بینید، ما در حال مقایسه هستیم که آیا deltaX بزرگتر از deltaY است تا تصمیم بگیریم که آیا کاربر به صورت افقی (چپ / راست) یا عمودی (بالا / پایین) حرکت کرده است.

اگر تند کشیدن افقی بود، پس:

منفی deltaX به این معنی است که آنها به سمت چپ کشیدند.

deltaX مثبت به این معنی است که آنها به سمت راست حرکت کردند.

اگر تند کشیدن عمودی بود، پس:

منفی deltaY به این معنی است که آنها به سمت بالا سوایپ کردند.

deltaY مثبت به این معنی است که آنها به سمت پایین سوایپ کردند.

اکنون، بیایید روی مولفه MobileSwiper تمرکز کنیم. می توانید آن را در بیانیه return پیدا کنید. ما کمک کننده handleSwipe را به ویژگی onSwipe می‌دهیم و کل کد HTML مؤلفه Board را می‌پیچانیم تا کشیدن روی آن فعال شود.

حالا وقتی آن را امتحان می کنیم، نتیجه ایده آل نیست. همانطور که در زیر می بینید، رویدادهای پیمایش با تند کشیدن تلفن همراه ترکیب می شوند:

game-v2-passive-true
صفحه با رویدادهای تکراری - کشیدن انگشت و پیمایش

این به این دلیل اتفاق می افتد که مرورگرهای مدرن از شنوندگان رویداد غیرفعال برای بهبود تجربه اسکرول در دستگاه های تلفن همراه استفاده می کنند. این بدان معناست که preventDefault که به تماس‌های رویداد خود اضافه کرده‌ایم هرگز اتفاق نمی‌افتد.

برای غیرفعال کردن رفتار پیمایش، باید شنوندگان غیرفعال را در مؤلفه MobileSwiper غیرفعال کنیم:

 import { useCallback, useEffect, useState, useRef } from "react" export default function MobileSwiper({ children, onSwipe }) { // ... removed to improve visibility ... useEffect(() => { window.addEventListener("touchstart", handleTouchStart, { passive: false }) window.addEventListener("touchend", handleTouchEnd, { passive: false }) // ... removed to improve visibility ... }, [handleTouchStart, handleTouchEnd]) // ... removed to improve visibility ... }

اکنون رفتار اسکرول از بین رفته است و بازی 2048 بسیار عالی به نظر می رسد:

game-v2-works
نتیجه نهایی - کشیدن انگشت کار می کند!

🏁 خلاصه

امروز به شما نشان دادم که برای مدیریت حرکات موبایل در React همیشه به کتابخانه نیاز ندارید. برخی از رویدادهای ساده مانند کشیدن انگشت را می توان با استفاده از ویژگی های اولیه React پیاده سازی کرد. ما فقط از یک دسته قلاب React استفاده کردیم و دو کنترل کننده رویداد ساده نوشتیم.

کل پیاده سازی دقیقاً 50 خط کد دارد. امیدوارم به شما انگیزه داده باشم که سعی کنید به تنهایی با رویدادهای تلفن همراه مقابله کنید.

اگر این مقاله به شما کمک کرد، لطفاً در توییتر به من اطلاع دهید . مربیانی مثل من اغلب احساس می‌کنند که ما در خلأ صحبت می‌کنیم و هیچ‌کس به آنچه آموزش می‌دهیم اهمیتی نمی‌دهد. یک «فریاد» ساده نشان می‌دهد که ارزش تلاش را داشت و به من انگیزه می‌دهد تا محتوای بیشتری از این دست ایجاد کنم.

لطفا این مقاله را در شبکه های اجتماعی خود به اشتراک بگذارید. متشکرم!

🎥 بازی 2048 خود را بسازید

این مقاله بخشی از دوره آموزشی من در Udemy است که در آن نحوه ایجاد یک بازی کاملاً کاربردی 2048 در Next.js را از ابتدا آموزش می‌دهم.

🧑‍🎓 به دوره Next.js من در Udemy بپیوندید

برای ثبت نام از کد FREECODECAMP استفاده کنید تا 60 درصد تخفیف دریافت کنید.

من معتقدم برنامه نویسی باید سرگرم کننده باشد و خلاقیت را آزاد کند. شما مجبور نیستید فهرست TODO دیگری یا یک سبد خرید بسازید. در عوض، می‌توانید چیزی بسازید که بتوانید به دوستانتان یا شاید حتی یک مدیر استخدام نشان دهید!

PS. اگر ترجیح می دهید فیلم های صفحه نمایش را تماشا کنید، پس این درس به صورت رایگان در Udemy در دسترس است. می‌توانید آن را در بخش « طرح‌بندی پاسخ‌گو و ویژگی بازی از دست رفته » در سخنرانی به نام « طرح‌بندی بازی و تند کشیدن‌های موبایل » پیدا کنید.

خبرکاو

ارسال نظر

دیدگاه‌ها بسته شده‌اند.


تبليغات ايهنا تبليغات ايهنا

تمامی حقوق مادی و معنوی این سایت متعلق به خبرکاو است و استفاده از مطالب با ذکر منبع بلامانع است