يمتلك Android ميزة شيقة جدًا في عرض الرسوم المتحركة يسمى CircularRevealAnimation
- حرفيًا "الكشف الدائري". إن Flutter ، على الرغم من أنه يتمتع بقدرات غنية لعناصر الرسوم المتحركة ، لا يوفر مثل هذه الرسوم المتحركة من خارج الصندوق.

ستوضح هذه المقالة كيفية تنفيذ هذه الرسوم المتحركة باستخدام Flutter ونشر المكتبة على pub.dev لسهولة الوصول إليها وتوزيعها.
تنفيذ الرسوم المتحركة
في رفرفة ، كل شيء هو القطعة. والرسوم المتحركة ليست استثناء. لذلك ، نقوم بإنشاء فئة CircularRevealAnimation
، والتي ستقوم بتوسيع فئة StatelessWidget
.
يتم البدء ووقف وضوابط الرسوم المتحركة الأخرى باستخدام AnimationController
. لإنشاء AnimationController
تحتاج إلى أن ترث من StatefulWidget
وإضافة فئة خاصة من SingleTickerProviderStateMixin
إلى State
.
لن تكون فئة الرسوم المتحركة لدينا CircularRevealAnimation
مسؤولة عن إدارة الرسوم المتحركة بمفردها ، ولكنها ستتلقى Animation<double>
كمعلمة مُنشئ مطلوبة ، لذلك ليست هناك حاجة إلى الإرث من StatefulWidget
. يتم ذلك بحيث يمكن بسهولة دمج CircularRevealAnimation
مع الرسوم المتحركة الأخرى التي تستخدم نفس AnimationController
. على سبيل المثال ، ادمج الرسوم المتحركة للإفصاح مع الشفافية في تغيير الرسوم المتحركة.
معلمة مهمة أخرى منشئ CircularRevealAnimation
هي child
، وهو عنصر فرعي من الرسوم المتحركة لدينا ، والتي سوف تظهر أو تختفي. بشكل عام ، في Flutter ، تحتوي الكثير من عناصر واجهة التعامل على معلمة تابعة. تتيح لك هذه الأدوات المصغّرة تغيير سلوك عنصر واجهة مستخدم أو تقديمه أو تصميمه. أو أضف رسومًا متحركة ، كما يحدث مع CircularRevealAnimation
.
بالإضافة إلى ذلك ، لتحديد الرسوم المتحركة ، ستكون هناك حاجة إلى معلمات مثل مركز فتح (أو إغلاق) الرسوم المتحركة ، وكذلك الحد الأدنى والحد الأقصى لنصف قطر الافتتاح. هذه المعلمات اختيارية ويمكن تحديدها على أنها null
أو غير محددة على الإطلاق عند إنشاء رسم متحرك. في هذه الحالة ، سيتم استخدام القيم الافتراضية: سيكون مركز الكشف في وسط عنصر واجهة المستخدم ، وسيتم إصابة الحد الأدنى لنصف القطر إلى الصفر ، وسيكون الحد الأقصى لنصف القطر مساوياً للمسافة من مركز الكشف إلى قمة القطعة التي هي الأكثر بعداً عن مركز الكشف.
خوارزمية حساب الحد الأقصى لنصف القطر الافتراضي هي كما يلي. أولاً ، يتم حساب المسافات الأفقية والرأسية من المركز إلى الرأس بعيدًا عن مركز الكشف ، ثم يتم حساب القطر بواسطة نظرية فيثاغورس.
static double calcMaxRadius(Size size, Offset center) { final w = max(center.dx, size.width - center.dx); final h = max(center.dy, size.height - center.dy); return sqrt(w * w + h * h); }
أنت الآن بحاجة إلى تطبيق اقتصاص عنصر واجهة المستخدم داخل الدائرة أثناء العرض. سوف ClipPath
فئة ClipPath
هذا الأمر ، والذي يتيح لك اقتصاص عنصر واجهة المستخدم وفقًا لقالب تعسفي. كمعلمات ، يتم تمرير أداة clipper
(في وقت لاحق قليلاً) child
هو عنصر واجهة المستخدم الذي يجب اقتصاصه.
تحدد المعلمة clipper
من عنصر واجهة ClipPath
كيفية اقتصاص عنصر واجهة المستخدم الفرعية. لإنشاء قالب الاقتصاص الخاص بك ، قم بإنشاء فئة CircularRevealClipper
التي ترث فئة CustomClipper<Path>
وإعادة تعريف أسلوب Path getClip(Size size)
. تُرجع هذه الطريقة مسارًا يربط منطقة الاقتصاص. في حالتنا ، هذه المنطقة عبارة عن دائرة بها مركز معين. لحساب نصف قطر الدائرة ، تحتاج إلى معرفة القيمة الحالية للرسوم المتحركة. يتم تمرير هذه القيمة إلى CircularRevealClipper
كمعلمة fraction
. يتم حساب نصف قطر الدائرة باستخدام الاستيفاء الخطي بين الحد الأدنى والحد الأقصى لنصف القطر.
بعد ذلك ، دعنا ننتقل إلى تنفيذ القطعة. أنها مريحة لاستخدام AnimatedBuilder
لإنشاء الرسوم المتحركة. يقبل مُنشئ AnimatedBuilder
كائن Animation<double>
builder
المستخدم في إنشاء عناصر واجهة مستخدم استنادًا إلى قيمة الحركة الحالية. في builder
نقوم بإنشاء ClipPath
القيمة الحالية للرسوم المتحركة ( fraction
) إلى CircularRevealClipper
.
class CircularRevealAnimation extends StatelessWidget { ... @override Widget build(BuildContext context) { return AnimatedBuilder( animation: animation, builder: (BuildContext context, Widget _) { return ClipPath( clipper: CircularRevealClipper( fraction: animation.value, center: center, minRadius: minRadius, maxRadius: maxRadius, ), child: this.child, ); }, ); } }
هذا يكمل إنشاء CircularRevealAnimation
. يبقى لاستخدامه. للقيام بذلك ، قم بإنشاء StatefulWidget
، AnimationController
وقم بتمرير AnimationController
إلى CircularRevealAnimation
.
مثال للاستخدام import 'package:flutter/material.dart'; import 'package:circular_reveal_animation/circular_reveal_animation.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'CRA Demo', theme: ThemeData( primarySwatch: Colors.blue, ), home: MyHomePage(), ); } } class MyHomePage extends StatefulWidget { @override _MyHomePageState createState() => _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> with SingleTickerProviderStateMixin { AnimationController animationController; Animation<double> animation; @override void initState() { super.initState(); animationController = AnimationController( vsync: this, duration: Duration(milliseconds: 1000), ); animation = CurvedAnimation( parent: animationController, curve: Curves.easeIn, ); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text("CRA Demo"), ), body: Padding( padding: const EdgeInsets.all(16.0), child: CircularRevealAnimation( minRadius: 12, maxRadius: 200, center: Offset(0, 300), child: Container(color: Colors.red), animation: animation, ), ), floatingActionButton: FloatingActionButton(onPressed: () { if (animationController.status == AnimationStatus.forward || animationController.status == AnimationStatus.completed) { animationController.reverse(); } else { animationController.forward(); } }), ); } }
جيثب التجريبي التطبيق .
إنشاء مكتبة
لإنشاء مكتبة Dart أو Flutter ، تحتاج إلى إضافة ملف pubspec.yaml
إلى نفس الدليل كدليل lib
مع ملفات Dart. يحتوي هذا الملف على وصف للمكتبة ومعلومات عن المؤلفين والتبعيات.
من الممارسات الجيدة أيضًا إنشاء ملف يحدد واجهة برمجة تطبيقات عامة. يوجد هذا الملف في مجلد lib
ويتضمن اسم المكتبة وقائمة الملفات التي يجب تضمينها في واجهة برمجة التطبيقات العامة. يتم وضع جميع ملفات Dart الأخرى في دليل src
. هذا لا يخفي فقط الملفات التي لم يتم تضمينها في واجهة برمجة التطبيقات العامة ، ولكنه يسمح لك أيضًا باستيراد المكتبة باستخدام تعبير import
واحد. محتويات هذا الملف :
library circular_reveal_animation; export 'package:circular_reveal_animation/src/circular_reveal_animation.dart';
يمكنك قراءة المزيد حول إنشاء مكتبات على Dart هنا .
نشر مكتبة Dart على pub.dev أمر بسيط للغاية. كل ما عليك فعله هو تشغيل الأمر flutter packages pub publish
من الدليل الجذر للمكتبة. يتم النشر نيابةً عن حساب Google ، لذا أثناء عملية النشر ، سيتم إعطاء رابط يجب فتحه في متصفح وتسجيل الدخول إلى Google. وبالتالي ، لا يمكن نشر التحديثات إلا باستخدام الحساب الذي تم نشر الإصدار الأول نيابة عنه.
قبل النشر ، يوصى بالتحقق من صحة المكتبة باستخدام الأمر flutter packages pub publish --dry-run
.
بعد تشغيل flutter packages pub publish
ستصبح المكتبة متاحة على pub.dev على الفور. وكما تقول الوثائق ، "النشر للأبد" - يمكنك لاحقًا تحميل إصدارات جديدة فقط. سوف الإصدارات القديمة تكون متاحة أيضا.
على الرغم من أن نشر المكتبة يبدو بسيطًا ، إلا أنه قد يكون له عيوب. على سبيل المثال ، عند نشر الإصدار الأول ، أُخذت مني بضع نقاط في التصنيف لأن وصف المكتبة (في pubspec.yaml
) كان قصيرًا جدًا.
يمكنك قراءة المزيد حول نشر المكتبات هنا .
في الواقع ، مكتبة circular_reveal_animation
على pub.dev و github.com .
ملاحظة: استخدمت ```java {...} ```
لتسليط الضوء على رمز Dart. سيكون من الجميل أن تضيف كود Dart لتسليط الضوء على habr.com.