الفرق بين المراجعتين لصفحة: «ReactNative/panresponder»

من موسوعة حسوب
طلا ملخص تعديل
 
(7 مراجعات متوسطة بواسطة مستخدمين اثنين آخرين غير معروضة)
سطر 1: سطر 1:
<noinclude>{{DISPLAYTITLE:الواجهة PanResponder في React Native}}</noinclude>
توحِّد الواجهة <code>PanResponder</code> العديد من اللمسات ضمن إيماءةٍ واحدة، وتجعل الإيماءة أحاديّة اللّمسة متجاوبةً مع اللّمسات الإضافيّة، ويمكن استخدامها للتعرُّف على الإيماءات الأساسيّة متعدّدة اللّمسات.


= PanResponder =
تحتوي <code>PanResponder</code> افتراضيًّا على معالجٍ باسم <code>InteractionManager</code> لمنع أحداث JS طويلة الأمد من مقاطعة الإيماءات الجارية، وتُقدِّم <code>panresponder</code> غلافًا يمكن التّنبؤ به لمعالجات المستجيب (responder handlers) المُقدَّم من [[ReactNative/gesture responder system|نظام مستجيب الإيماءات (gesture responder system)]]، حيث تعطي لكلّ معالجٍ كائنًا جديدًا <code>gestureState</code> بجانب كائن الحدَث الأصيل: <syntaxhighlight lang="javascript">
توحِّد <code>PanResponder</code> العديد من اللمسات ضمن إيماءةٍ واحدة، وتجعل الإيماءة أحاديّة اللّمسة متجاوبةً مع اللّمسات الإضافيّة، ويمكن أن تُستخدم للتعرُّف على الإيماءات الأساسيّة متعدّدة اللّمسات.
 
تحتوي <code>PanResponder</code> بشكل افتراضيٍّ على معالجٍ باسم <code>InteractionManager</code> لمنع أحداث JS طويلة الأمد من مقاطعة الإيماءات الجارية.
 
تُقدِّم <code>panresponder</code> غلافًا يمكن التنبؤ به لمعالجات المستجيب (responder handlers) المُقدَّم من نظام مستجيب الإيماءات [https://reactnative.dev/docs/gesture-responder-system gesture responder system]، حيث تعطي لكل معالجٍ كائنًا جديدًا <code>gestureState</code> بجانب كائن الحدَث الأصيل: <syntaxhighlight lang="javascript">
onPanResponderMove: (event, gestureState) => {}
onPanResponderMove: (event, gestureState) => {}
</syntaxhighlight>الحدَث الأصيل هو عبارة عن حدَث لمسةٍ مصطنَعةٍ (synthetic) على شكل <code>[https://reactnative.dev/docs/pressevent PressEvent]</code>.
</syntaxhighlight>الحدَث الأصيل هو عبارة عن حدَث لمسةٍ مصطنَعةٍ (synthetic) على شكل كائن <code>[[ReactNative/pressevent|PressEvent]]</code>.


يتضمَّن الكائن <code>gestureState</code> ما يلي:
يتضمَّن الكائن <code>gestureState</code> ما يلي:


* <code>stateID</code>: مُعرِّف (ID) الكائن <code>gestureState</code> ويبقى ما دامت هنالك لمسة واحدة على الأقل على الشاشة.
* <code>stateID</code>: مُعرِّف (ID) الكائن <code>gestureState</code>، ويبقى ما دامت هنالك لمسة واحدة على الأقلّ على الشّاشة.
* <code>moveX</code>: الإحداثيات الأفقية الأخيرة على الشاشة للَّمسة المتحركة حديثًا.
* <code>moveX</code>: الإحداثيات الأفقيّة الأخيرة على الشّاشة للَّمسة المتحركة حديثًا.
* <code>moveY</code>:  الإحداثيات العموديّة الأخيرة على الشاشة للّمسة المتحركة حديثًا.
* <code>moveY</code>:  الإحداثيات العموديّة الأخيرة على الشّاشة للّمسة المتحركة حديثًا.
* <code>x0</code>: الإحداثيات الأفقية على الشاشة لمكان منحْ (grant) المستجيب.
* <code>x0</code>: الإحداثيات الأفقيّة على الشّاشة لمكان منح (grant) المستجيب.
* <code>y0</code>: الإحداثيات العموديّة على الشاشة لمكان منحْ المستجيب.
* <code>y0</code>: الإحداثيات العموديّة على الشّاشة لمكان منح المستجيب.
* <code>dx</code>: المسافة الأفقية المجمَّعة للإيماءة من لحظة بدء اللمسة.
* <code>dx</code>: المسافة الأفقيّة المجمَّعة للإيماءة من لحظة بدء اللّمسة.
* <code>dy</code>: المسافة العموديّة المجمَّعة للإيماءة من لحظة بدء اللمسة.
* <code>dy</code>: المسافة العموديّة المجمَّعة للإيماءة من لحظة بدء اللّمسة.
* <code>vx</code>: السرعة الأفقية الحالية للإيماءة.
* <code>vx</code>: السّرعة الأفقية الحاليّة للإيماءة.
* <code>vy</code>: السرعة العموديّة الحالية للإيماءة.
* <code>vy</code>: السّرعة العموديّة الحاليّة للإيماءة.
* <code>numberActiveTouches</code>: عدد اللمسات الحالية على الشاشة.
* <code>numberActiveTouches</code>: عدد اللّمسات الحالية على الشّاشة.


== نموذج الاستخدام ==
== مثال ==
<syntaxhighlight lang="javascript">
إليك أولًا عن نموذج لاستخادم الواجهة:<syntaxhighlight lang="javascript">


const ExampleComponent = () => {
const ExampleComponent = () => {
سطر 66: سطر 63:
  return <View {...panResponder.panHandlers} />;
  return <View {...panResponder.panHandlers} />;
};
};
</syntaxhighlight>
</syntaxhighlight>تُستخدم <code>panresponder</code> مع الواجهة البرمجية (API)‏ <code>[[ReactNative/animations|Animated]]</code> للمساعدة في إنشاء إيماءاتٍ معقّدةٍ في واجهة المستخدم (UI)، ويحتوي المثال التالي على المكون المتحرّك <code>[[ReactNative/view|View]]</code>، والذي يمكن سحبه بحريّةٍ عبر الشّاشة:


== مثال ==
* [https://snack.expo.dev/@hsoubwiki/panresponder-function-component مثال لمكون الدّالة (Function Component)]
تُستخدم <code>panresponder</code> مع الواجهة البرمجية (API)‏ <code>Animated</code> للمساعدة في إنشاء إيماءاتٍ معقّدةٍ في واجهة المستخدم (UI)، يحتوي المثال التالي على المكون المتحرّك <code>View</code> والذي يمكن سحبه بحريّةٍ عبر الشاشة:
 
* مثال لمكون الدالة (Function Component)
<syntaxhighlight lang="javascript">
<syntaxhighlight lang="javascript">


سطر 117: سطر 111:
</syntaxhighlight>
</syntaxhighlight>


* مثال لمكون الصنف (Class Component)
* [https://snack.expo.dev/@hsoubwiki/panresponder-class-component مثال لمكون الصّنف (Class Component)]
<syntaxhighlight lang="javascript">
<syntaxhighlight lang="javascript">


سطر 161: سطر 155:
  return <View {...panResponder.panHandlers} />;
  return <View {...panResponder.panHandlers} />;
};
};
</syntaxhighlight>جرِّب <code>[https://github.com/facebook/react-native/blob/master/packages/rn-tester/js/examples/PanResponder/PanResponderExample.js PanResponder example in RNTester]</code>.
</syntaxhighlight>جرِّب [https://github.com/facebook/react-native/blob/master/packages/rn-tester/js/examples/PanResponder/PanResponderExample.js مثال PanResponder في RNTester].


== التوابع ==
== التوابع ==
سطر 168: سطر 162:
<syntaxhighlight lang="javascript">
<syntaxhighlight lang="javascript">
static create(config)
static create(config)
</syntaxhighlight>
</syntaxhighlight>'''المعاملات''':
 
==== المعاملات ====
{| class="wikitable"
{| class="wikitable"
!الاسم
!الاسم
سطر 177: سطر 169:
!الوصف
!الوصف
|-
|-
|config
|<code>config</code>
|كائن
|كائن (object)
    object
|نعم
|نعم
|الشرح في الأسفل
|الشرح في الأسفل
|}
|}
يُقدِّم الكائن <code>config</code> إصدارات محسَّنة لجميع ردود نداء المستجيب (responder callbacks)، والذي بدوره لا يُقدِّم <code>[https://reactnative.dev/docs/pressevent PressEvent]</code> فقط بل حالة الإيماءات <code>PanResponder</code> أيضًا، وذلك باستبدال الكلمة <code>Responder</code> بالكلمة <code>PanResponder</code> في كل استجابة نموذجيّةٍ <code>onResponder*</code>. كمثال على ذلك سيبدو الكائن <code>config</code> كما يلي:
يُقدِّم الكائن <code>config</code> إصدارات محسَّنة لجميع ردود نداء المستجيب (responder callbacks)، والذي بدوره لا يُقدِّم <code>PressEvent</code> فقط بل حالة الإيماءات <code>PanResponder</code> أيضًا، وذلك باستبدال الكلمة <code>Responder</code> بالكلمة <code>PanResponder</code> في كل استجابة نموذجيّةٍ <code>onResponder*</code>. كمثال على ذلك سيبدو الكائن <code>config</code> كما يلي:<syntaxhighlight lang="javascript">
 
onMoveShouldSetPanResponder: (e, gestureState) => {...}
* <code>onMoveShouldSetPanResponder: (e, gestureState) => {...}</code>
onMoveShouldSetPanResponderCapture: (e, gestureState) => {...}
* <code>onMoveShouldSetPanResponderCapture: (e, gestureState) => {...}</code>
onStartShouldSetPanResponder: (e, gestureState) => {...}
* <code>onStartShouldSetPanResponder: (e, gestureState) => {...}</code>
onStartShouldSetPanResponderCapture: (e, gestureState) => {...}
* <code>onStartShouldSetPanResponderCapture: (e, gestureState) => {...}</code>
onPanResponderReject: (e, gestureState) => {...}
* <code>onPanResponderReject: (e, gestureState) => {...}</code>
onPanResponderGrant: (e, gestureState) => {...}
* <code>onPanResponderGrant: (e, gestureState) => {...}</code>
onPanResponderStart: (e, gestureState) => {...}
* <code>onPanResponderStart: (e, gestureState) => {...}</code>
onPanResponderEnd: (e, gestureState) => {...}
* <code>onPanResponderEnd: (e, gestureState) => {...}</code>
onPanResponderRelease: (e, gestureState) => {...}
* <code>onPanResponderRelease: (e, gestureState) => {...}</code>
onPanResponderMove: (e, gestureState) => {...}
* <code>onPanResponderMove: (e, gestureState) => {...}</code>
onPanResponderTerminate: (e, gestureState) => {...}
* <code>onPanResponderTerminate: (e, gestureState) => {...}</code>
onPanResponderTerminationRequest: (e, gestureState) => {...}
* <code>onPanResponderTerminationRequest: (e, gestureState) => {...}</code>
onShouldBlockNativeResponder: (e, gestureState) => {...}
* <code>onShouldBlockNativeResponder: (e, gestureState) => {...}</code>
</syntaxhighlight>وبالنسبة للأحداث التي لها مكافئات في طور الالتقاط (أي طور انتشار الحدث من العنصر الجذر وحتى العنصر الهدف capture phase)، نُحدِّث <code>gestureState</code> مرةً واحدةً فقط أثناء طور الالتقاط (capture phase) مباشرةً، ويمكن استخدامه في طور الانتشار (bubble phase، أو طور الغليان أو الفوران حيث ينتشر الحدث من العنصر الهدف وحتى الأعلى باتجاه العنصر الجذر) أيضًا.   
 
وبالنسبة للأحداث التي لها مكافئات في طور الالتقاط (أي طور إنتشار الحدث من العنصر الجذر وحتى العنصر الهدف capture phase)، نُحدِّث <code>gestureState</code> مرةً واحدةً فقط أثناء طور الالتقاط (capture phase) مباشرةً، ويمكن استخدامه في طور الانتشار (bubble phase، أو طور الغليان أو الفوران حيث ينتشر الحدث من العنصر الهدف وحتى الأعلى باتجاه العنصر الجذر) أيضًا.   


يجب الانتباه عند التعامل مع الاستجابات <code>onStartShould*</code> لأنها تعكس <code>gestureState</code>  لأحداث البدء أو الانتهاء لطوري العقدة (الفقاعة أو الالتقاط). فعندما تصبح العقدة هي المستجيب يمكن الوثوق بأن الإيماءة تعالج كلّ حدث بدءٍ أو انتهاءٍ، ويحدَّث <code>gestureState</code> تبعًا لذلك.، قد لا يكون <code>numberActiveTouches</code> دقيقًا تمامًا إلا إذا كنت أنت المستجيب.
يجب الانتباه عند التعامل مع الاستجابات <code>onStartShould*</code> لأنّها تعكس <code>gestureState</code>  لأحداث البدء، أو الانتهاء لطوري العقدة (الفقاعة أو الالتقاط)، فعندما تصبح العقدة هي المستجيب يمكن الوثوق بأن الإيماءة تعالج كلّ حدث بدءٍ، أو انتهاءٍ، ويحدَّث <code>gestureState</code> تبعًا لذلك، وقد لا يكون <code>numberActiveTouches</code> دقيقًا تمامًا إلّا إذا كنت أنت المستجيب.


== مصادر ==
== مصادر ==


* [https://facebook.github.io/react-native/docs/panresponder صفحة PanResponder في توثيق React Native الرسميّ]
* [https://facebook.github.io/react-native/docs/panresponder صفحة PanResponder في توثيق React Native الرسميّ]
[[تصنيف:ReactNative]]
[[تصنيف:React Native API]]

المراجعة الحالية بتاريخ 14:13، 9 أكتوبر 2021

توحِّد الواجهة PanResponder العديد من اللمسات ضمن إيماءةٍ واحدة، وتجعل الإيماءة أحاديّة اللّمسة متجاوبةً مع اللّمسات الإضافيّة، ويمكن استخدامها للتعرُّف على الإيماءات الأساسيّة متعدّدة اللّمسات.

تحتوي PanResponder افتراضيًّا على معالجٍ باسم InteractionManager لمنع أحداث JS طويلة الأمد من مقاطعة الإيماءات الجارية، وتُقدِّم panresponder غلافًا يمكن التّنبؤ به لمعالجات المستجيب (responder handlers) المُقدَّم من نظام مستجيب الإيماءات (gesture responder system)، حيث تعطي لكلّ معالجٍ كائنًا جديدًا gestureState بجانب كائن الحدَث الأصيل:

onPanResponderMove: (event, gestureState) => {}

الحدَث الأصيل هو عبارة عن حدَث لمسةٍ مصطنَعةٍ (synthetic) على شكل كائن PressEvent.

يتضمَّن الكائن gestureState ما يلي:

  • stateID: مُعرِّف (ID) الكائن gestureState، ويبقى ما دامت هنالك لمسة واحدة على الأقلّ على الشّاشة.
  • moveX: الإحداثيات الأفقيّة الأخيرة على الشّاشة للَّمسة المتحركة حديثًا.
  • moveY: الإحداثيات العموديّة الأخيرة على الشّاشة للّمسة المتحركة حديثًا.
  • x0: الإحداثيات الأفقيّة على الشّاشة لمكان منح (grant) المستجيب.
  • y0: الإحداثيات العموديّة على الشّاشة لمكان منح المستجيب.
  • dx: المسافة الأفقيّة المجمَّعة للإيماءة من لحظة بدء اللّمسة.
  • dy: المسافة العموديّة المجمَّعة للإيماءة من لحظة بدء اللّمسة.
  • vx: السّرعة الأفقية الحاليّة للإيماءة.
  • vy: السّرعة العموديّة الحاليّة للإيماءة.
  • numberActiveTouches: عدد اللّمسات الحالية على الشّاشة.

مثال

إليك أولًا عن نموذج لاستخادم الواجهة:

const ExampleComponent = () => {
 const panResponder = React.useRef(
  PanResponder.create({
   // طلب المكوِّن ليكون المستجيب
   onStartShouldSetPanResponder: (evt, gestureState) => true,
   onStartShouldSetPanResponderCapture: (evt, gestureState) =>
    true,
   onMoveShouldSetPanResponder: (evt, gestureState) => true,
   onMoveShouldSetPanResponderCapture: (evt, gestureState) =>
    true,

   onPanResponderGrant: (evt, gestureState) => {
    // بدأت الإيماءة. أظهر مراجعة مرئية ليعلم المستخدم ما يحدث
    //بالقيمة الصفرية gestureState.d{x,y} سيتم الآن تهيئة
    },
   onPanResponderMove: (evt, gestureState) => {
    // gestureState.move{X,Y}آخر مسافة محدَّثة للحركة
    //المسافة المجمَّعة للإيماءة منذ أن أصبح المكون مستجيبا 
    // gestureState.d{x,y}
    },
   onPanResponderTerminationRequest: (evt, gestureState) =>
    true,
   onPanResponderRelease: (evt, gestureState) => {
    // حررَ المستخدم جميع اللمسات عند ظهور المستجيب
    // مما يدل عمليًا على نجاح الإيماءة
    },
   onPanResponderTerminate: (evt, gestureState) => {
    // أصبح مكوِّن آخر هو المستجيب
    // لذا سيتم إنهاء هذه الإيماءة
    },
   onShouldBlockNativeResponder: (evt, gestureState) => {
    // عند منعَ المكون المكونات الأصيلة من true إرجاع قيمة 
    // true  والقيمة الافتراضية هي، JS أن تصبح مستجيب
    //  فقط Android مدعومة حاليا في نظام 
    return true;
    }
   })
  ).current;

 return <View {...panResponder.panHandlers} />;
};

تُستخدم panresponder مع الواجهة البرمجية (API)‏ Animated للمساعدة في إنشاء إيماءاتٍ معقّدةٍ في واجهة المستخدم (UI)، ويحتوي المثال التالي على المكون المتحرّك View، والذي يمكن سحبه بحريّةٍ عبر الشّاشة:

const ExampleComponent = () => {
 const panResponder = React.useRef(
  PanResponder.create({
   // طلب المكوِّن ليكون المستجيب
   onStartShouldSetPanResponder: (evt, gestureState) => true,
   onStartShouldSetPanResponderCapture: (evt, gestureState) =>
    true,
   onMoveShouldSetPanResponder: (evt, gestureState) => true,
   onMoveShouldSetPanResponderCapture: (evt, gestureState) =>
    true,

   onPanResponderGrant: (evt, gestureState) => {
    // بدأت الإيماءة. أظهر مراجعة مرئية ليعلم المستخدم ما يحدث
    //بالقيمة الصفرية gestureState.d{x,y} سيتم الآن تهيئة
    },
   onPanResponderMove: (evt, gestureState) => {
    // gestureState.move{X,Y}آخر مسافة محدَّثة للحركة
    //المسافة المجمَّعة للإيماءة منذ أن أصبح المكون مستجيبا 
    // gestureState.d{x,y}
    },
   onPanResponderTerminationRequest: (evt, gestureState) =>
    true,
   onPanResponderRelease: (evt, gestureState) => {
    // حررَ المستخدم جميع اللمسات عند ظهور المستجيب
    // مما يدل عمليًا على نجاح الإيماءة
    },
   onPanResponderTerminate: (evt, gestureState) => {
    // أصبح مكوِّن آخر هو المستجيب
    // لذا سيتم إنهاء هذه الإيماءة
    },
   onShouldBlockNativeResponder: (evt, gestureState) => {
    // عند منعَ المكون المكونات الأصيلة من true إرجاع قيمة 
    // true  والقيمة الافتراضية هي، JS أن تصبح مستجيب
    //  فقط Android مدعومة حاليا في نظام 
    return true;
    }
   })
  ).current;

 return <View {...panResponder.panHandlers} />;
};
const ExampleComponent = () => {
 const panResponder = React.useRef(
  PanResponder.create({
   // طلب المكوِّن ليكون المستجيب
   onStartShouldSetPanResponder: (evt, gestureState) => true,
   onStartShouldSetPanResponderCapture: (evt, gestureState) =>
    true,
   onMoveShouldSetPanResponder: (evt, gestureState) => true,
   onMoveShouldSetPanResponderCapture: (evt, gestureState) =>
    true,

   onPanResponderGrant: (evt, gestureState) => {
    // بدأت الإيماءة. أظهر مراجعة مرئية ليعلم المستخدم ما يحدث
    //بالقيمة الصفرية gestureState.d{x,y} سيتم الآن تهيئة
    },
   onPanResponderMove: (evt, gestureState) => {
    // gestureState.move{X,Y}آخر مسافة محدَّثة للحركة
    //المسافة المجمَّعة للإيماءة منذ أن أصبح المكون مستجيبا 
    // gestureState.d{x,y}
    },
   onPanResponderTerminationRequest: (evt, gestureState) =>
    true,
   onPanResponderRelease: (evt, gestureState) => {
    // حررَ المستخدم جميع اللمسات عند ظهور المستجيب
    // مما يدل عمليًا على نجاح الإيماءة
    },
   onPanResponderTerminate: (evt, gestureState) => {
    // أصبح مكوِّن آخر هو المستجيب
    // لذا سيتم إنهاء هذه الإيماءة
    },
   onShouldBlockNativeResponder: (evt, gestureState) => {
    // عند منعَ المكون المكونات الأصيلة من true إرجاع قيمة 
    // true  والقيمة الافتراضية هي، JS أن تصبح مستجيب
    //  فقط Android مدعومة حاليا في نظام 
    return true;
    }
   })
  ).current;

 return <View {...panResponder.panHandlers} />;
};

جرِّب مثال PanResponder في RNTester.

التوابع

create()‎

static create(config)

المعاملات:

الاسم النوع مطلوب الوصف
config كائن (object) نعم الشرح في الأسفل

يُقدِّم الكائن config إصدارات محسَّنة لجميع ردود نداء المستجيب (responder callbacks)، والذي بدوره لا يُقدِّم PressEvent فقط بل حالة الإيماءات PanResponder أيضًا، وذلك باستبدال الكلمة Responder بالكلمة PanResponder في كل استجابة نموذجيّةٍ onResponder*‎. كمثال على ذلك سيبدو الكائن config كما يلي:

onMoveShouldSetPanResponder: (e, gestureState) => {...}
onMoveShouldSetPanResponderCapture: (e, gestureState) => {...}
onStartShouldSetPanResponder: (e, gestureState) => {...}
onStartShouldSetPanResponderCapture: (e, gestureState) => {...}
onPanResponderReject: (e, gestureState) => {...}
onPanResponderGrant: (e, gestureState) => {...}
onPanResponderStart: (e, gestureState) => {...}
onPanResponderEnd: (e, gestureState) => {...}
onPanResponderRelease: (e, gestureState) => {...}
onPanResponderMove: (e, gestureState) => {...}
onPanResponderTerminate: (e, gestureState) => {...}
onPanResponderTerminationRequest: (e, gestureState) => {...}
onShouldBlockNativeResponder: (e, gestureState) => {...}

وبالنسبة للأحداث التي لها مكافئات في طور الالتقاط (أي طور انتشار الحدث من العنصر الجذر وحتى العنصر الهدف capture phase)، نُحدِّث gestureState مرةً واحدةً فقط أثناء طور الالتقاط (capture phase) مباشرةً، ويمكن استخدامه في طور الانتشار (bubble phase، أو طور الغليان أو الفوران حيث ينتشر الحدث من العنصر الهدف وحتى الأعلى باتجاه العنصر الجذر) أيضًا.

يجب الانتباه عند التعامل مع الاستجابات onStartShould*‎ لأنّها تعكس gestureState لأحداث البدء، أو الانتهاء لطوري العقدة (الفقاعة أو الالتقاط)، فعندما تصبح العقدة هي المستجيب يمكن الوثوق بأن الإيماءة تعالج كلّ حدث بدءٍ، أو انتهاءٍ، ويحدَّث gestureState تبعًا لذلك، وقد لا يكون numberActiveTouches دقيقًا تمامًا إلّا إذا كنت أنت المستجيب.

مصادر