احتراف الـ Canvas: لماذا أراهن على Skia و Reanimated لواجهات مستخدم عالية الدقة
توقف عن الاكتفاء بـ standard views وتعلم كيفية استغلال محرك Skia لرسومات عالية الأداء. أشارككم رحلتي في تجاوز الـ bridge لبناء تجارب سلسة بسرعة 60FPS تشعرك بأنها native تماماً.

احتراف الـ Canvas: لماذا أراهن على Skia و Reanimated لواجهات مستخدم عالية الدقة
لسنوات، كان بناء واجهات مستخدم (UIs) عالية الدقة للأجهزة المحمولة باستخدام React Native يبدو وكأنه معركة مستمرة ضد الـ 'Bridge'. لقد مررنا جميعاً بهذا الموقف: محاولة تنسيق animations معقدة لنفاجأ بـ dropped frames أو ذلك البطء المزعج عندما ينشغل الـ JS thread.
لكن المشهد قد تغير الآن. إذا كنت لا تزال تحاول بناء تصورات بيانات (data visualizations) معقدة أو واجهات انسيابية تشبه الألعاب باستخدام مكونات View و Animated القياسية، فأنت تصطدم بسقف تقني لم تعد مضطراً للتعامل معه. مؤخراً، تحول سير عملي بالكامل نحو الثنائي القوي: React Native Skia و Reanimated 3.
إليك كيف أستخدم هذه الأدوات لدفع حدود الممكن في تطوير التطبيقات العابرة للمنصات (cross-platform development).
التحول في الفلسفة: Graphics مقابل Layout
في React Native القياسي، نفكر بمنطق Flexbox و Views المتداخلة. هذا أمر رائع للنماذج والقوائم. ولكن عندما تريد تأثير gooey متقلب، أو خلفية مخصصة تعتمد على shader، أو رسماً بيانياً لمراقبة الصحة في الوقت الفعلي، فإن العبء الإضافي لمحرك layout yoga وهيكلية الـ native view يصبح عائقاً.
يوفر لنا React Native Skia محرك رسومات 2D (نفس المحرك الذي يشغل Chrome و Flutter) مباشرة داخل شجرة React الخاصة بنا. نتوقف هنا عن التفكير في 'components' ونبدأ في التفكير في 'draw calls'.
السر الكامن: Shared Values بصفتها الرابط
الاختراق الحقيقي يحدث عندما تسد الفجوة بين declarative API الخاص بـ Skia و worklets الخاصة بـ Reanimated. ولأن مكونات Skia يمكنها الاستجابة مباشرة لـ Reanimated SharedValues دون إطلاق عملية re-render في React، يمكننا تحقيق 60FPS (أو 120FPS على شاشات ProMotion) حتى في أكثر المشاهد تعقيداً.
مثال عملي: The Morphing Blob
عملت مؤخراً على ميزة تتطلب خلفية عضوية انسيابية. القيام بذلك باستخدام SVGs القياسية كان سيكون كابوساً من حيث الأداء على أجهزة Android المتوسطة. مع Skia، الأمر في غاية البساطة.
دروس من الميدان
بعد ترحيل عدة نماذج (modules) ذات كثافة استخدام عالية إلى Skia، تعلمت بضعة دروس ثمينة:
-
استخدم
useDerivedValueبكثافة: لا تقم بحساب المسارات (paths) أو النقاط داخل جسم مكونCanvas. انقل كل المنطق الثقيل إلى Reanimated hooks. هذا يضمن أن الشيء الوحيد الذي يحدث على الـ JS thread هو الـ mounting الأولي فقط. -
الـ Shaders هي صديقك المفضل: واحدة من أكثر الميزات التي لا تقدّر حق قدرها في RN Skia هي القدرة على كتابة custom GLSL shaders. إذا كنت بحاجة إلى gradient معقد أو تأثير blur لا ينهك الـ GPU، فاكتب shader. أداؤه أفضل بكثير من وضع خمس مكونات
Viewفوق بعضها مع تأثير blur. -
فخ الـ Texture: كن حذراً مع الصور الكبيرة. تحميل textures ضخمة في Skia يمكن أن يستهلك ذاكرة كبيرة. استخدم دائماً
useImagehooks وفكر في تقليل حجم الملفات (downscaling) قبل أن تصل إلى الـ canvas.
متى لا تستخدم Skia
بقدر ما أحب هذه الأدوات، لا أزال مهندساً برمجياً أول، مما يعني أنني أعرف متى أقول 'لا'.
لا تستخدم Skia للنصوص التي تتطلب accessibility أو لمدخلات النماذج (form inputs) القياسية. مكونات React Native الأصلية (native components) محسنة بالفعل لقارئات الشاشة وتفاعلات لوحة المفاتيح على مستوى نظام التشغيل. Skia هي مساحة للرسم؛ استخدمها فيما تجيده—اللمسات البصرية الجمالية، تصور البيانات، والـ micro-interactions—وليس لبناء واجهة التطبيق بالكامل.
خاتمة
لقد أدى الجمع بين Skia و Reanimated إلى محو 'فجوة الأداء' التي كنت أشعر بها سابقاً بين React Native و Swift/Kotlin. لم نعد محدودين بالـ bridge؛ نحن محدودون فقط بخيالنا.
إذا لم تكن قد استكشفلت توثيق @shopify/react-native-skia بعد، فافعل ذلك اليوم. سيغير ذلك طريقة تفكيرك في تطوير تطبيقات الهاتف المحمول.