انیمیشن های اسکرول افقی در React Native — به زبان ساده

۹۲ بازدید
آخرین به‌روزرسانی: ۲۰ شهریور ۱۴۰۲
زمان مطالعه: ۴ دقیقه
انیمیشن های اسکرول افقی در React Native — به زبان ساده

در این نوشته به لینک کردن <Animated> با <ScrollView> می‌پردازیم تا یک انیمیشن UI ناوبری زیبا برای اسکرول افقی در React Native بسازیم.

React Native امکان ساخت UI-های زیبا و نرم را ارائه می‌کند.
React Native امکان ساخت UI-های زیبا و نرم را ارائه می‌کند.

پیش‌نیازها

  • React Native
  • شبیه‌ساز
  • به هیچ کتابخانه شخص ثالثی هم نیاز نداریم!

ایجاد کامپوننت Screen با <Animated>

ابتدا Animated, Dimensions, ScrollView, StyleSheet, Text, View را از “react-native” ایمپورت می‌کنیم. سپس یک کامپوننت می‌سازیم که به عنوان یک screen یا view با آن رفتار می‌کنیم.

//We declare this here because the device width will be used for scrollView again
const SCREEN_WIDTH = Dimensions.get("window").width;
//Screen component
const Screen = props => {
  return (
    <View style={styles.scrollPage}>
      //we are going to write animation function and pass it to here
      <Animated.View style={[styles.screen, transitionAnimation(props.index)]}>
        <Text style={styles.text}>{props.text}</Text>
      </Animated.View>
    </View>
  );
};
//Styles
const styles = StyleSheet.create({
  scrollPage: {
    width: SCREEN_WIDTH,
    padding: 20
  },
  screen: {
    height: 600,
    justifyContent: "center",
    alignItems: "center",
    borderRadius: 25,
    backgroundColor: "white"
  },
  text: {
fontSize: 45,

ما در این مقاله از Animated.View استفاده می‌کنیم، چون قصد داریم این کامپوننت پوششی را انیمیت کنیم. عرض استایل scrollPage و (transitionAnimation(props.index مهم هستند، زیرا ما قصد داریم مقادیر اسکرول افقی را برای ضرب کردن مقادیر انیمیشن میان‌یابی کنیم. به بیان دیگر ما می‌خواهیم ردگیری کنیم که صفحه کجا قرار دارد تا کامپوننت صفحه را بر مبنای آن مقدار انیمیت کنیم.

این جزء مواردی است که توضیح آن دشوار است؛ اما جزو نکات کلیدی برای درک کارکرد مطرح شده در این مقاله به حساب می‌آید.

امیدواریم با دیدن این تصویر بیش از پیش سردرگم نشده باشید.

در واقع ما انیمیشن‌ها را بر مبنای مقدار اسکرول x لینک می‌کنیم. فرض کنید عرض دستگاه ما 100 باشد، وقتی کاربر به سمت چپ سوایپ می‌کند و می‌خواهد به صفحه بعد برود، می‌توانیم آن صفحه را به صورت 2×100 و 3×100 و همین طور تا آخر توصیف کنیم. بنابراین اگر انیمیشن را در 0 آغاز کرده باشیم و در 200 خاتمه دهیم، می‌توانیم بازه ورودی و بازه خروجی را به صورت زیر بنویسیم:

inputRange: [
            (index - 1) * SCREEN_WIDTH,
            index * SCREEN_WIDTH,
            (index + 1) * SCREEN_WIDTH
          ],
outputRange: [
            "entering animation", 
            "screen in the middle no transform", 
            "exiting animation"
]

اگر عرض صفحه برابر با 100 باشد، این مقدار برای index = 1 برابر با [200, 100, 0] و برای index = 2 برابر با [300, 200, 100] خواهد بود. وقتی موقعیت اسکرول در 150 باشد، صفحه اول در نیمه مسیر خروج و صفحه دوم در نیمه مسیر ورود قرار دارند.

افزودن انیمیشن‌ها

از آنجا که همه موارد لازم را آماده کرده‌ایم، اینک زمان آن رسیده است که انیمیشن‌ها را بنویسیم. باید از مقدار index به عنوان یک خصوصیت (prop) استفاده کنیم و از این رو می‌توانیم یک تابع بنویسیم که آرایه‌ای از انیمیشن‌های transform مانند زیر بازگشت دهد:

const xOffset = new Animated.Value(0);

const transitionAnimation = index => {
  return {
    transform: [
      { perspective: 800 },
      {
        scale: xOffset.interpolate({
          inputRange: [
            (index - 1) * SCREEN_WIDTH,
            index * SCREEN_WIDTH,
            (index + 1) * SCREEN_WIDTH
          ],
          outputRange: [0.25, 1, 0.25]
        })
      },
      {
        rotateX: xOffset.interpolate({
          inputRange: [
            (index - 1) * SCREEN_WIDTH,
            index * SCREEN_WIDTH,
            (index + 1) * SCREEN_WIDTH
          ],
          outputRange: ["45deg", "0deg", "45deg"]
        })
      },
      {
        rotateY: xOffset.interpolate({
          inputRange: [
            (index - 1) * SCREEN_WIDTH,
            index * SCREEN_WIDTH,
            (index + 1) * SCREEN_WIDTH
          ],
          outputRange: ["-45deg", "0deg", "45deg"]
})

دقت کنید که Animated.Value برای افست x، مسئول ردگیری مقادیر ورودی و خروجی انیمیشن‌ها است. ما به سه مورد از آن‌ها نیاز نداریم، زیرا inputRange یعنی عرض دستگاه در هر سه انیمیشن یکسان است.

Scale برای اندازه کامپوننت screen و rotateX و rotateY برای چرخش‌ها استفاده می‌شوند. همان طور که می‌بینید transform آرایه‌ای از شیءها می‌پذیرد و چرخش‌ها را که نیازمند String بیان شده بر مبنای درجه هستند را اجرا می‌کند.

در این نوشته قصد نداریم وارد جزییات کتابخانه Animated بشویم؛ اگر می‌خواهید در این خصوص بیشتر بدانید می‌توانید از آموزش‌ها و مطالب دیگر فرادرس در مورد React Native کمک بگیرید.

لینک کردن انیمیشن‌ها به ScrollView

این گام آخر است. ما قصد داریم از ScrollView برای یکپارچه‌سازی سیستم پاسخ‌دهی قفل کردن لمس استفاده کنیم. برای این که این وضعیت کار کند باید چند prop را ارسال کنیم:

const xOffset = new Animated.Value(0);

const transitionAnimation = index => {
  return {
    transform: [
      { perspective: 800 },
      {
        scale: xOffset.interpolate({
          inputRange: [
            (index - 1) * SCREEN_WIDTH,
            index * SCREEN_WIDTH,
            (index + 1) * SCREEN_WIDTH
          ],
          outputRange: [0.25, 1, 0.25]
        })
      },
      {
        rotateX: xOffset.interpolate({
          inputRange: [
            (index - 1) * SCREEN_WIDTH,
            index * SCREEN_WIDTH,
            (index + 1) * SCREEN_WIDTH
          ],
          outputRange: ["45deg", "0deg", "45deg"]
        })
      },
      {
        rotateY: xOffset.interpolate({
          inputRange: [
            (index - 1) * SCREEN_WIDTH,
            index * SCREEN_WIDTH,
            (index + 1) * SCREEN_WIDTH
          ],
          outputRange: ["-45deg", "0deg", "45deg"]
})

ابتدا با توضیح scrollEventThrottle آغاز می‌کنیم. این خصوصیت مسئول کنترل کردن توالی (frequency) رویداد است. Horizontal امکان اسکرول کردن افقی را فراهم می‌سازد. ما مقدار xOffset را که قبل‌تر اعلان شده بود ارسال می‌کنیم و useNativeDrive را برابر با true تنظیم می‌کنیم. این امر ضروری است زیرا این کار به کد native امکان می‌دهد که انیمیشن را روی نخ UI بدون تبدیل جاوا اسکریپت روی هر فریم اجرا کند. اگر این مقدار false باشد، انیمیشن Screen دچار گیر کردن می‌شود.

همه مراحل مورد نیاز همین بود. اگر همه چیز را درست انجام داده باشید، با انیمیشنی مانند زیر مواجه می‌شوید:

React Native امکان ساخت UI-های زیبا و نرم را ارائه می‌کند.

سخن پایانی

اگر قصد دارید از این انیمیشن برای ناوبری‌های ساده استفاده کنید، گزینه مناسبی محسوب می‌شود. با این وجود، اگر می‌خواهید این انیمیشن را روی فهرست بلندی از آیتم‌ها اجرا کنید، چند نکته را باید مورد توجه قرار دهید. کامپوننت ScrollView همه کامپوننت‌های فرزند را رندر می‌کند. از این رو اگر می‌خواهید با فهرست بلندی کار کنید، ممکن است با کُندی عملکرد مواجه شوید. در این صورت باید به جای آن از FlatList استفاده کنید که آیتم‌ها را به صورت lazy رندر می‌کند و بدین ترتیب در حافظه و زمان مورد نیاز برای پردازش صرفه‌جویی می‌کند. همچنین می‌بایست inputRange متفاوت بنویسید، زیرا FlatList آیتم‌هایی که از صفحه به طرف بیرون اسکرول می‌شوند را حذف می‌کند.

اگر این مطلب برایتان مفید بوده است آموزش‌های زیر نیز به شما پیشنهاد می‌شوند:

==

بر اساس رای ۰ نفر
آیا این مطلب برای شما مفید بود؟
اگر بازخوردی درباره این مطلب دارید یا پرسشی دارید که بدون پاسخ مانده است، آن را از طریق بخش نظرات مطرح کنید.
منابع:
codeburst
نظر شما چیست؟

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *