الرسوم المتحركة وتصميم الحركة

رسوم Lottie المتحركة: دمج الرسوم المتجهة بصيغة JSON

16 دقيقة الدرس 12 من 13

رسوم Lottie المتحركة: دمج الرسوم المتجهة بصيغة JSON

Lottie هو تنسيق رسوم متحركة مفتوح المصدر طورته شركة Airbnb يُعيد رسم رسوم Adobe After Effects المتحركة في الوقت الفعلي باستخدام بيانات متجهية مُصدَّرة بصيغة JSON. بدلاً من شحن ملفات GIF ثقيلة أو صفحات الرسوم، تقوم بتحميل ملف .json خفيف الوزن يُعيد Flutter رسمه كرسوميات متجهة واضحة وقابلة للتوسع عند أي كثافة شاشة. والنتيجة رسوم متحركة سلسة جداً بأحجام ملفات صغيرة وتحكم برمجي كامل في التشغيل.

إضافة حزمة lottie

أضف حزمة lottie الرسمية إلى تبعيات ملف pubspec.yaml:

pubspec.yaml

dependencies:
  flutter:
    sdk: flutter
  lottie: ^3.1.0        # استخدم دائماً أحدث إصدار مستقر

flutter:
  assets:
    - assets/animations/  # المجلد الذي يحتوي على ملفات .json

شغّل flutter pub get بعد الحفظ. ضع ملفات الرسوم المتحركة .json داخل assets/animations/. يمكنك تحميل رسوم متحركة مجانية من LottieFiles.com أو تصديرها بنفسك من After Effects باستخدام إضافة Bodymovin.

ملاحظة: يمكن تحميل ملفات Lottie .json أيضاً من الشبكة عبر رابط URL أو من الذاكرة كبيانات خام — وليس فقط من حزم الأصول المحلية. سنتناول أسلوب الأصول أولاً لأنه الأكثر شيوعاً في تطبيقات الإنتاج.

عرض رسوم Lottie المتحركة

أبسط طريقة لعرض ملف Lottie هي استخدام منشئ Lottie.asset(). يتصرف مثل أي ودجت Flutter آخر ويمكن وضعه في أي مكان في شجرة الودجات:

ودجت Lottie الأساسي

import 'package:flutter/material.dart';
import 'package:lottie/lottie.dart';

class SplashScreen extends StatelessWidget {
  const SplashScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.white,
      body: Center(
        child: Lottie.asset(
          'assets/animations/rocket_launch.json',
          width: 300,
          height: 300,
          fit: BoxFit.contain,
          // autoplay و loop كلاهما يساوي true افتراضياً
        ),
      ),
    );
  }
}

افتراضياً، يبدأ Lottie.asset() التشغيل فوراً ويُعيد الحلقة إلى الأبد. تتحكم معاملات width وheight وfit في حجم الودجت تماماً كودجت Image.

التحكم في التشغيل باستخدام AnimationController

للتحكم الكامل — الإيقاف المؤقت والعكس وضبط السرعة والاستماع للاكتمال — تحتاج إلى StatefulWidget مع AnimationController. مرّر المتحكم إلى معامل controller لودجت Lottie:

AnimationController مع Lottie

import 'package:flutter/material.dart';
import 'package:lottie/lottie.dart';

class LoadingScreen extends StatefulWidget {
  const LoadingScreen({super.key});

  @override
  State<LoadingScreen> createState() => _LoadingScreenState();
}

class _LoadingScreenState extends State<LoadingScreen>
    with SingleTickerProviderStateMixin {
  late AnimationController _controller;

  @override
  void initState() {
    super.initState();
    _controller = AnimationController(vsync: this);
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Lottie.asset(
              'assets/animations/loading_dots.json',
              controller: _controller,
              width: 200,
              height: 200,
              onLoaded: (composition) {
                // اضبط المدة من بيانات JSON ثم ابدأ الحلقة
                _controller
                  ..duration = composition.duration
                  ..repeat();
              },
            ),
            const SizedBox(height: 24),
            Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                ElevatedButton(
                  onPressed: () => _controller.forward(),
                  child: const Text('تشغيل'),
                ),
                const SizedBox(width: 12),
                ElevatedButton(
                  onPressed: () => _controller.stop(),
                  child: const Text('إيقاف مؤقت'),
                ),
                const SizedBox(width: 12),
                ElevatedButton(
                  onPressed: () => _controller.reverse(),
                  child: const Text('عكس'),
                ),
              ],
            ),
          ],
        ),
      ),
    );
  }
}
نصيحة: اقرأ دائماً مدة الرسوم المتحركة من composition.duration داخل رد النداء onLoaded بدلاً من ترميز Duration ثابتة. كل ملف JSON من Lottie يحتوي على مدته المقصودة، وضبطها من البيانات الوصفية يضمن تشغيلاً مثالياً الإطارات بغض النظر عن كيفية تصدير المصمم للملف.

ضبط سرعة التشغيل

تُتحكم السرعة عن طريق قياس مدة المتحكم. الأسلوب المتعارف عليه هو تعديل _controller.duration لتحقيق السرعة المطلوبة:

تغيير السرعة أثناء التشغيل

// نصف السرعة: ضاعف المدة
_controller.duration = composition.duration * 2;

// ضعف السرعة: انصف المدة
_controller.duration = composition.duration * 0.5;

// يمكنك عرض مضاعف السرعة عبر شريط تمرير:
double _speed = 1.0;

Slider(
  value: _speed,
  min: 0.25,
  max: 3.0,
  onChanged: (value) {
    setState(() {
      _speed = value;
      _controller.duration = composition.duration * (1 / _speed);
    });
  },
)

الاستجابة لاكتمال الرسوم المتحركة

لتشغيل كود عند انتهاء رسوم متحركة غير متكررة، أضف StatusListener إلى المتحكم. هذا هو نمط Flutter القياسي للرسوم المتحركة ويعمل بنفس الطريقة مع Lottie:

رد نداء الاكتمال

@override
void initState() {
  super.initState();
  _controller = AnimationController(vsync: this);

  // الاستماع للاكتمال
  _controller.addStatusListener((status) {
    if (status == AnimationStatus.completed) {
      // انتهت الرسوم المتحركة — الانتقال أو تحديث الواجهة
      Navigator.of(context).pushReplacementNamed('/home');
    }
  });
}

// في onLoaded: تشغيل مرة واحدة (بدون تكرار)
onLoaded: (composition) {
  _controller
    ..duration = composition.duration
    ..forward();
}
تحذير: لا تستدعِ Navigator أو setState داخل addStatusListener دون التحقق أولاً من if (mounted). قد يُشغَّل مستمع الحالة بعد التخلص من الودجت مما يُطلق FlutterError. احمِ جميع الآثار الجانبية بـ if (!mounted) return;.

التحميل من الشبكة

يمكنك جلب رسوم Lottie المتحركة من رابط بعيد باستخدام Lottie.network(). هذا مفيد للرسوم المتحركة ذات السمات الديناميكية المخزنة على شبكة CDN:

Lottie من الشبكة

Lottie.network(
  'https://assets5.lottiefiles.com/packages/lf20_success.json',
  width: 200,
  height: 200,
  errorBuilder: (context, error, stackTrace) {
    return const Icon(Icons.error_outline, size: 64);
  },
)

الملخص

تندمج رسوم Lottie المتحركة في Flutter بحد أدنى من الكود: أضف حزمة lottie، أعلن عن أصول .json، واستخدم Lottie.asset() للرسوم المتحركة البسيطة ذاتية التشغيل. للتحكم التفاعلي، اقرن الودجت بـ AnimationController، اقرأ المدة من onLoaded، واستخدم addStatusListener للاستجابة للاكتمال. تعديلات السرعة بسيطة مثل قياس مدة المتحكم، مما يجعل Lottie أداة قوية وسهلة الاستخدام لأي مطور Flutter.

النقطة الرئيسية: يُعيد Lottie رسم الرسوم المتجهة القابلة للتوسع من JSON بشكل أصلي في Flutter. استخدم Lottie.asset() مع القيم الافتراضية autoplay: true وrepeat: true للرسوم المتحركة الزخرفية الثابتة، وأدخل AnimationController عندما تحتاج إلى تشغيل/إيقاف مؤقت أو سرعة أو خطافات الاكتمال.