الواجهة Easing في React Native

من موسوعة حسوب

تُطبِّق وحدة التسارع ‎‎Easing‎‎ دوال التسارع الشائعة (easing functions). تُستخدم هذه الوحدة من طرف ‎‎Animated.timing()‎‎ لعرض حركة معقولة فيزيائيًّا في التحريكات.

يمكنك العثور على تجسيد مرئيّ لبعض دوال التسارع الشائعة على easings.net.

التحريكات المعرفة مسبقا (Predefined animations)

توفر وحدة Easing العديد من التحريكات المُعرَّفة مسبقًا من خلال التوابع التالية:

  • ‎‎back‎‎: يوفر تحريكًا بسيطًا يعود فيه الكائن للوراء قليلاً قبل التحرك للأمام.
  • ‎‎bounce‎‎: يُوفِّر تحريك ارتدادٍ.
  • ‎‎ease‎‎: يوفر تحريك قصور ذاتي أساسي (basic inertial animation).
  • ‎‎elastic‎‎: يوفر تفاعل وثبٍ أساسي (basic spring interaction).

الدوال قياسية

تتوفّر ثلاث دوال تسارع قياسية:

  • ‎‎linear‎‎
  • ‎‎quad‎‎
  • ‎‎cubic‎‎

يمكن استخدام الدالة poly لتنفيذ دوال ذات قوة جبرية (power function) أعلى مثل الرباعيّة (quartic) والخماسيّة (quintic) وغيرها.

دوال إضافيّة

تتوفّر دوال رياضية إضافية عبر التوابع التالية:

  • ‎‎bezier ‎‎: يوفر منحنى بيزيه مكعب.
  • ‎‎circle ‎‎: يوفر دالة دائرية.
  • ‎‎sin ‎‎: يوفر دالة جيبية (sinusoidal function).
  • ‎‎exp ‎‎: يوفر دالة أسية (exponential function).

تُستخدم التوابع المساعدة التالية لتعديل دوال تسارعٍ أخرى.

  • ‎‎in ‎‎: يُنفِّذ دالة تسارع إلى الأمام.
  • ‎‎inOut ‎‎: يجعل أي دالة تسارع متناظرة (symmetrical).
  • ‎‎out ‎‎: يُنفِّذ دالة تسارع إلى الخلف.

مثال

إليك المثال التالي (تجربة حية):

import React from "react";
import { Animated, Easing, SectionList, StatusBar, StyleSheet, Text, TouchableOpacity, View } from "react-native";

const App = () => {
  let opacity = new Animated.Value(0);

  const animate = easing => {
    opacity.setValue(0);
    Animated.timing(opacity, {
      toValue: 1,
      duration: 1200,
      easing
    }).start();
  };

  const size = opacity.interpolate({
    inputRange: [0, 1],
    outputRange: [0, 80]
  });

  const animatedStyles = [
    styles.box,
    {
      opacity,
      width: size,
      height: size
    }
  ];

  return (
    <View style={styles.container}>
      <StatusBar hidden={true} />
      <Text style={styles.title}>
        Press rows below to preview the Easing!
      </Text>
      <View style={styles.boxContainer}>
        <Animated.View style={animatedStyles} />
      </View>
      <SectionList
        style={styles.list}
        sections={SECTIONS}
        keyExtractor={(item) => item.title}
        renderItem={({ item }) => (
          <TouchableOpacity
            onPress={() => animate(item.easing)}
            style={styles.listRow}
          >
            <Text>{item.title}</Text>
          </TouchableOpacity>
        )}
        renderSectionHeader={({ section: { title } }) => (
          <Text style={styles.listHeader}>{title}</Text>
        )}
      />
    </View>
  );
};

const SECTIONS = [
  {
    title: "Predefined animations",
    data: [
      { title: "Bounce", easing: Easing.bounce },
      { title: "Ease", easing: Easing.ease },
      { title: "Elastic", easing: Easing.elastic(4) }
    ]
  },
  {
    title: "Standard functions",
    data: [
      { title: "Linear", easing: Easing.linear },
      { title: "Quad", easing: Easing.quad },
      { title: "Cubic", easing: Easing.cubic }
    ]
  },
  {
    title: "Additional functions",
    data: [
      {
        title: "Bezier",
        easing: Easing.bezier(0, 2, 1, -1)
      },
      { title: "Circle", easing: Easing.circle },
      { title: "Sin", easing: Easing.sin },
      { title: "Exp", easing: Easing.exp }
    ]
  },
  {
    title: "Combinations",
    data: [
      {
        title: "In + Bounce",
        easing: Easing.in(Easing.bounce)
      },
      {
        title: "Out + Exp",
        easing: Easing.out(Easing.exp)
      },
      {
        title: "InOut + Elastic",
        easing: Easing.inOut(Easing.elastic(1))
      }
    ]
  }
];

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: "#20232a"
  },
  title: {
    marginTop: 10,
    textAlign: "center",
    color: "#61dafb"
  },
  boxContainer: {
    height: 160,
    alignItems: "center"
  },
  box: {
    marginTop: 32,
    borderRadius: 4,
    backgroundColor: "#61dafb"
  },
  list: {
    backgroundColor: "#fff"
  },
  listHeader: {
    paddingHorizontal: 8,
    paddingVertical: 4,
    backgroundColor: "#f4f4f4",
    color: "#999",
    fontSize: 12,
    textTransform: "uppercase"
  },
  listRow: {
    padding: 8
  }
});

export default App;

التوابع

‎‎step0()‎‎

static step0(n)

دالة زحزحة (stepping function)، تُعيد القيمة ‎‎1‎‎ لأي قيمة ‎‎n‎‎ موجبة.

‎‎step1()‎‎

static step1(n)

دالة زحزحة، تُعيد القيمة ‎‎1‎‎ إذا كانت ‎‎n‎‎ أكبر من أو تساوي ‎1‎‎.

‎‎linear()‎‎

static linear(t)

دالة خطية،‎‎f(t) = t ‎‎. الموقع يرتبط بالوقت المنقضي واحد لواحد (one to one). مثال

‎‎ease()‎‎

static ease(t)

تفاعل قصور ذاتي أساسيّ، على غرار كائنٍ يتسارع ببطء إلى الإسراع. انظر هذا المثال.

‎‎quad()‎‎

static quad(t)

دالة تربيعية، ‎‎f(t) = t * t‎‎. يساوي الموقع مربع الوقت المنقضي. انظر هذا المثال.

‎‎cubic()‎‎

static cubic(t)

دالة تكعيبية، ‎‎f(t) = t * t * t‎‎. يساوي الموقع مكعب الوقت المنقضي. انظر هذا المثال.

‎‎poly()‎‎

static poly(n)

دالة قوة جبريّة (power function). يساوي الموقعُ الوقتَ المنقضي أُس ‎‎n‎‎. انظر مثال n = 4 وأيضًا مثال n = 5.

‎‎sin()‎‎

static sin(t)

دالة جيبية. انظر هذا المثال.

‎‎circle()‎‎

static circle(t)

دالة دائرية. انظر هذا المثال.

‎‎exp()‎‎

static exp(t)

دالة أسية. انظر هذا المثال.

‎‎elastic()‎‎

static elastic(bounciness)

تفاعل مرن أساسي (basic elastic interaction)، يشبه واثبًا (spring) يتأرجح ذهابًا وإيابًا.

قيمة ‎‎bounciness‎‎ الافتراضية هي ‎‎1‎‎، والتي تتجاوز الحد (overshoot) قليلًا مرة واحدة. القيمة ‎‎0‎‎ لا تتجاوز الحد إطلاقًا، وقيمة ‎‎N > 1‎‎ ستتجاوز الحد عدد N مرات تقريبًا.

انظر هذا المثال.

‎‎back()‎‎

static back(s)

استخدمه مع ‎‎Animated.parallel()‎‎ لإنشاء تأثير أساسي يُحرَّك فيه الكائن للوراء قليلاً مع بدء الحركة.

‎‎bounce()‎‎

static bounce(t)

يوفر تأثير ارتداد أساسي. انظر هذا المثال.

‎‎bezier()‎‎

static bezier(x1, y1, x2, y2)

يوفر منحنى بيزيه مكعب (cubic bezier curve)، أي ما يعادل الانتقال ‎‎transition-timing-function‎‎ الخاص بلغة CSS.

الموقع cubic-bezier.com أداةٌ مفيدة لتجسيد منحنيات بيزيه المكعبة.

‎‎in()‎‎

static in(easing);

يُنفِّذ دالة تسارع إلى الأمام.

‎‎out()‎‎

static out(easing)

يُنفِّذ دالة تسارع إلى الخلف.

‎‎inOut()‎‎

static inOut(easing)

يجعل أي دالة تسارع متناظرة (symmetrical). ستُنفَّذ دالة التسارع للأمام لنصف المدة، ثم للخلف لبقية المدة.

مصادر