+1

Hướng dẫn cơ bản về Rive trong Flutter

Giới thiệu

Arc 2025-02-08 14.21.31.png Rive (trước đây được biết đến với tên Flare) là một nền tảng animation mạnh mẽ cho phép các nhà thiết kế và lập trình viên tạo ra các animation tương tác có thể chạy trên nhiều nền tảng khác nhau. Điểm đặc biệt là Rive có thể chuyển đổi các file animation từ Adobe After Effects và Lottie sang định dạng .riv, giúp giảm thiểu việc phải viết animation controller thủ công.

Rive là gì?

Rive là một công cụ thiết kế động cho phép bạn tạo ra các animation vector có thể tương tác và điều khiển được trong thời gian thực. Nó cung cấp:

  1. Khả năng tạo animation vector phức tạp

    • Hỗ trợ nhiều loại animation
    • Tích hợp với Adobe After Effects
    • Chuyển đổi từ Lottie files
  2. Tương tác thời gian thực

    • Điều khiển animation dựa trên input người dùng
    • State machines cho logic phức tạp
    • Runtime events và callbacks
  3. Tối ưu hiệu năng

    • File size nhỏ gọn
    • Hiệu suất cao khi chạy
    • Hardware acceleration

Tại sao nên chọn Rive?

1. Tương thích đa nền tảng

  • Hoạt động mượt mà trên nhiều thiết bị
  • Thích ứng với các kích thước màn hình khác nhau
  • Tích hợp dễ dàng với nhiều framework

2. Hiệu suất tối ưu

  • Vector graphics cho chất lượng cao
  • Hardware acceleration cho animation mượt mà
  • Tiêu thụ tài nguyên tối thiểu

3. Workflow hiệu quả

  • Tạo animated tutorials và onboarding sequences
  • Microinteractions cho UX tốt hơn
  • Thư viện animation có sẵn phong phú

Tích hợp Rive vào Flutter

1. Cài đặt

dependencies:
  rive: ^latest_version

2. Các Phương Pháp Tích Hợp

a. Qua URL

RiveAnimation.network(
  'https://rive.app/community/animation-url',
  fit: BoxFit.cover,
)

b. Qua Asset

RiveAnimation.asset(
  'assets/animations/your_animation.riv',
  fit: BoxFit.cover,
)

c. Theo artbroad

class OptimizedRiveWidget extends StatefulWidget {
  
  _OptimizedRiveWidgetState createState() => _OptimizedRiveWidgetState();
}

class _OptimizedRiveWidgetState extends State<OptimizedRiveWidget> {
  Artboard? _artboard;
  RiveFile? _riveFile;
  StateMachineController? _controller;

  
  void initState() {
    super.initState();
    _loadRiveFile();
  }

  Future<void> _loadRiveFile() async {
    try {
      final bytes = await rootBundle.load('assets/animations/example.riv');
      final file = RiveFile.import(bytes);
      final artboard = file.mainArtboard;
      
      var controller = StateMachineController.fromArtboard(artboard, 'main');
      if (controller != null) {
        artboard.addController(controller);
      }
      
      setState(() {
        _riveFile = file;
        _artboard = artboard;
        _controller = controller;
      });
    } catch (e) {
      print('Error loading Rive file: $e');
    }
  }

  
  Widget build(BuildContext context) {
    return _artboard == null
      ? CircularProgressIndicator()
      : Rive(artboard: _artboard!);
  }

  
  void dispose() {
    _controller?.dispose();
    super.dispose();
  }
}

Các Thành Phần Chính

1. Artboards

image.png

  • Nền tảng của mọi composition
  • Root của hierarchy
  • Định nghĩa kích thước và màu nền
  • Chứa nhiều animations và state machines

2. State Machines

Arc 2025-02-08 14.30.54.png State Machines là một phương pháp trực quan để kết nối các animation với nhau và định nghĩa logic điều khiển chuyển đổi giữa chúng. Chúng cho phép xây dựng các đồ họa chuyển động tương tác sẵn sàng để triển khai

class RiveStateMachineExample extends StatefulWidget {
  
  _RiveStateMachineExampleState createState() => _RiveStateMachineExampleState();
}

class _RiveStateMachineExampleState extends State<RiveStateMachineExample> {
  Artboard? _artboard;
  StateMachineController? _controller;
  SMIBool? _isHovered;
  SMITrigger? _clickTrigger;

  
  void initState() {
    super.initState();
    _loadRiveFile();
  }

  Future<void> _loadRiveFile() async {
    try {
      final bytes = await rootBundle.load('assets/animations/example.riv');
      final file = RiveFile.import(bytes);
      final artboard = file.mainArtboard;
      
      // Khởi tạo State Machine
      var controller = StateMachineController.fromArtboard(
        artboard,
        'state_machine_name', // Tên của state machine trong Rive
      );
      
      if (controller != null) {
        artboard.addController(controller);
        
        // Lấy các inputs từ state machine
        _isHovered = controller.findSMI('isHovered') as SMIBool?;
        _clickTrigger = controller.findSMI('click') as SMITrigger?;
      }
      
      setState(() {
        _artboard = artboard;
        _controller = controller;
      });
    } catch (e) {
      print('Error loading Rive file: $e');
    }
  }

  void _handleStateChange() {
    // Xử lý chuyển đổi state
    if (_isHovered != null) {
      _isHovered!.value = !_isHovered!.value;
    }
  }

  void _triggerClick() {
    // Kích hoạt trigger
    if (_clickTrigger != null) {
      _clickTrigger!.fire();
    }
  }

  
  Widget build(BuildContext context) {
    return GestureDetector(
      onTapDown: (_) => _triggerClick(),
      onHover: (isHovered) {
        if (_isHovered != null) {
          _isHovered!.value = isHovered;
        }
      },
      child: _artboard == null
          ? CircularProgressIndicator()
          : Container(
              width: 200,
              height: 200,
              child: Rive(artboard: _artboard!),
            ),
    );
  }

  
  void dispose() {
    _controller?.dispose();
    super.dispose();
  }
}

3. Custom Controllers

StateMachineController là một lớp trong Rive Flutter dùng để:

  • Điều khiển và quản lý các state machine trong animation Rive
  • Xử lý các input và trigger từ người dùng
  • Kiểm soát chuyển đổi giữa các trạng thái animation
class RiveExample extends StatefulWidget {
  
  _RiveExampleState createState() => _RiveExampleState();
}

class _RiveExampleState extends State<RiveExample> {
  Artboard? _artboard;
  StateMachineController? _controller;
  
  
  void initState() {
    super.initState();
    // Khởi tạo controller
    _loadRiveFile();
  }

  Future<void> _loadRiveFile() async {
    final bytes = await rootBundle.load('assets/example.riv');
    final file = RiveFile.import(bytes);
    final artboard = file.mainArtboard;
    
    // Tạo controller từ artboard
    var controller = StateMachineController.fromArtboard(
      artboard,
      'state_machine_name' // Tên state machine trong file Rive
    );
    
    if (controller != null) {
      // Thêm controller vào artboard
      artboard.addController(controller);
    }
    
    setState(() {
      _artboard = artboard;
      _controller = controller;
    });
  }
}

Best Practices

1. Tối ưu hóa Assets

  • Giữ file .riv nhỏ gọn
  • Sử dụng compression khi có thể
  • Tối ưu số lượng artboards

2. State Machine Management

  • Sử dụng state machines thay vì animations riêng lẻ
  • Tổ chức logic chuyển đổi rõ ràng
  • Xử lý states một cách hiệu quả

3. Performance Optimization

class PerformanceOptimizedRive extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return RepaintBoundary(
      child: RiveAnimation.asset(
        'assets/animations/example.riv',
        antialiasing: true,
        useArtboardSize: true,
        fit: BoxFit.contain,
      ),
    );
  }
}

4. Error Handling

Future<void> loadAnimation() async {
  try {
    final bytes = await rootBundle.load('assets/animations/example.riv');
    final file = RiveFile.import(bytes);
    // Process file
  } on RiveException catch (e) {
    print('Rive error: ${e.message}');
  } on Exception catch (e) {
    print('General error: $e');
  }
}

Kết luận

Rive là một công cụ mạnh mẽ cho việc tạo và quản lý animation trong Flutter, mang đến khả năng tạo animation phức tạp, tương tác thời gian thực và hiệu suất cao. Với những ưu điểm về hiệu năng, tính linh hoạt và khả năng tương thích đa nền tảng, Rive là lựa chọn tuyệt vời cho các ứng dụng Flutter hiện đại cần animation chất lượng cao.

Một ứng dụng nhỏ sử dụng Rive để làm các hoạt ảnh, hiệu ứng: Terrarium idle

Watch the video


All rights reserved

Bình luận

Đăng nhập để bình luận
Avatar
+1
Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí