一、插件介绍

1.1 PAG动画格式概述

PAG(Portable Animated Graphics)是一种高性能的动画格式,由腾讯团队开发,支持复杂的矢量和光栅动画。它具有以下特点:

  • 跨平台兼容:支持iOS、Android、Web、OpenHarmony等多种平台
  • 高性能渲染:采用硬件加速,确保动画流畅运行
  • 体积小巧:高效的压缩算法,减少资源占用
  • 动态控制:支持动画进度、播放速度、循环次数等参数的实时调整
  • 交互支持:可检测点击区域的图层信息,实现交互式动画效果

1.2 flutter-pag插件功能

flutter-pag是一个专为Flutter框架开发的PAG动画集成插件,现已全面支持OpenHarmony平台。该插件提供了以下核心功能:

  • 支持从本地资源、网络URL和二进制数据加载PAG动画
  • 提供完整的动画控制API(播放、暂停、停止、进度调整等)
  • 支持动画循环次数设置和无限循环
  • 提供动画生命周期事件回调(开始、结束、重复、取消)
  • 支持获取指定坐标点下的图层信息,实现交互式动画
  • 支持加载失败时显示自定义占位组件
  • 针对OpenHarmony平台进行了专门优化,确保良好的性能和兼容性

二、环境要求与依赖引入

2.1 环境要求

使用flutter-pag插件前,需要确保开发环境满足以下要求:

  • Flutter SDK ≥ 1.20.0
  • Dart SDK ≥ 2.12.0
  • OpenHarmony SDK API ≥ 9
  • DevEco Studio ≥ 3.0(开发OpenHarmony应用时)

2.2 依赖引入

由于flutter-pag是自定义修改版本,需要通过git形式引入。在项目的pubspec.yaml文件中添加以下依赖配置:

dependencies:
  flutter:
    sdk: flutter

  pag:
    git:
      url: "https://atomgit.com/openharmony-tpc/flutter_packages.git"
      path: "packages/pag"

添加依赖后,执行以下命令获取依赖:

flutter pub get

三、API调用与使用示例

3.1 PAGView组件

PAGView是flutter-pag插件的核心组件,用于渲染PAG动画。它提供了三种构造方法,分别用于加载不同来源的PAG动画:

3.1.1 从本地资源加载
PAGView.asset(
  'assets/animation.pag',
  width: 200,
  height: 200,
  repeatCount: PAGView.REPEAT_COUNT_LOOP, // 无限循环
  autoPlay: true, // 自动播放
  onAnimationStart: () {
    print('动画开始播放');
  },
  onAnimationEnd: () {
    print('动画播放结束');
  },
)
3.1.2 从网络URL加载
PAGView.network(
  'https://example.com/animation.pag',
  width: 200,
  height: 200,
  repeatCount: 3, // 播放3次
  initProgress: 0.5, // 从50%进度开始播放
  onInit: () {
    print('动画初始化完成');
  },
)
3.1.3 从二进制数据加载
// 假设bytesData是从文件或网络获取的PAG二进制数据
Uint8List bytesData = ...;

PAGView.bytes(
  bytesData,
  width: 200,
  height: 200,
  autoPlay: false, // 不自动播放
  defaultBuilder: (context) {
    // 加载失败时显示的占位组件
    return Container(
      color: Colors.grey,
      alignment: Alignment.center,
      child: Text('加载中...'),
    );
  },
)

3.2 动画控制

通过GlobalKey<PAGViewState>可以获取PAGView的状态对象,从而调用各种动画控制方法:

// 创建GlobalKey
final GlobalKey<PAGViewState> pagKey = GlobalKey<PAGViewState>();

// 在PAGView中使用
PAGView.asset(
  'assets/animation.pag',
  key: pagKey,
  autoPlay: false,
);

// 播放动画
pagKey.currentState?.start();

// 暂停动画
pagKey.currentState?.pause();

// 停止动画
pagKey.currentState?.stop();

// 设置动画进度(0.0-1.0)
pagKey.currentState?.setProgress(0.75);

// 获取指定坐标点下的图层信息
Future<void> getLayers() async {
  List<String> layers = await pagKey.currentState?.getLayersUnderPoint(100, 100) ?? [];
  print('点击位置的图层信息:$layers');
}

3.3 动画事件监听

flutter-pag插件提供了完整的动画生命周期事件回调:

PAGView.asset(
  'assets/animation.pag',
  repeatCount: PAGView.REPEAT_COUNT_LOOP,
  onAnimationStart: () {
    print('动画开始播放');
  },
  onAnimationEnd: () {
    print('动画播放结束');
  },
  onAnimationRepeat: () {
    print('动画重复播放');
  },
  onAnimationCancel: () {
    print('动画被取消');
  },
)

3.4 OpenHarmony平台集成注意事项

在OpenHarmony平台上使用flutter-pag插件时,需要注意以下几点:

  1. 资源配置:确保PAG动画文件在pubspec.yaml中正确配置:
flutter:
  assets:
    - assets/animation.pag
  1. 权限配置:如果需要从网络加载PAG动画,需要在OpenHarmony应用的配置文件中添加网络权限:
{
  "module": {
    "requestPermissions": [
      {
        "name": "ohos.permission.INTERNET"
      }
    ]
  }
}
  1. 性能优化:对于复杂的PAG动画,建议适当限制渲染尺寸,避免过度占用系统资源:
PAGView.asset(
  'assets/complex_animation.pag',
  width: 300, // 限制宽度
  height: 300, // 限制高度
  autoPlay: true,
)

四、完整示例代码

4.1 基础使用示例

以下是一个完整的Flutter应用示例,展示了如何在OpenHarmony平台上使用flutter-pag插件:

import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:pag/pag.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return MaterialApp(
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final GlobalKey<PAGViewState> _localPagKey = GlobalKey<PAGViewState>();
  final GlobalKey<PAGViewState> _networkPagKey = GlobalKey<PAGViewState>();
  final GlobalKey<PAGViewState> _bytesPagKey = GlobalKey<PAGViewState>();

  Uint8List? _bytesData;
  bool _isPlaying = false;

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

  // 加载二进制数据
  void _loadBytesData() async {
    ByteData data = await rootBundle.load('assets/animation.pag');
    setState(() {
      _bytesData = data.buffer.asUint8List();
    });
  }

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Flutter PAG动画示例(OpenHarmony)'),
      ),
      body: SingleChildScrollView(
        padding: EdgeInsets.all(16),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            // 1. 本地资源加载示例
            Text('\n1. 本地资源加载示例', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
            SizedBox(height: 10),
            PAGView.asset(
              'assets/animation.pag',
              key: _localPagKey,
              width: 300,
              height: 300,
              repeatCount: PAGView.REPEAT_COUNT_LOOP,
              autoPlay: true,
              onAnimationStart: () {
                print('本地动画开始');
                setState(() => _isPlaying = true);
              },
              onAnimationEnd: () {
                print('本地动画结束');
                setState(() => _isPlaying = false);
              },
            ),
            SizedBox(height: 10),
            Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                ElevatedButton(
                  onPressed: () => _localPagKey.currentState?.start(),
                  child: Text('播放'),
                ),
                SizedBox(width: 10),
                ElevatedButton(
                  onPressed: () => _localPagKey.currentState?.pause(),
                  child: Text('暂停'),
                ),
                SizedBox(width: 10),
                ElevatedButton(
                  onPressed: () => _localPagKey.currentState?.stop(),
                  child: Text('停止'),
                ),
              ],
            ),

            // 2. 网络资源加载示例
            SizedBox(height: 30),
            Text('\n2. 网络资源加载示例', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
            SizedBox(height: 10),
            PAGView.network(
              'https://example.com/animation.pag',
              key: _networkPagKey,
              width: 300,
              height: 300,
              repeatCount: PAGView.REPEAT_COUNT_LOOP,
              autoPlay: true,
            ),

            // 3. 二进制数据加载示例
            SizedBox(height: 30),
            Text('\n3. 二进制数据加载示例', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
            SizedBox(height: 10),
            _bytesData != null
                ? PAGView.bytes(
                    _bytesData!,
                    key: _bytesPagKey,
                    width: 300,
                    height: 300,
                    repeatCount: 3,
                    autoPlay: false,
                    defaultBuilder: (context) => Container(
                      width: 300,
                      height: 300,
                      color: Colors.grey,
                      alignment: Alignment.center,
                      child: Text('加载中...'),
                    ),
                  )
                : Container(
                    width: 300,
                    height: 300,
                    color: Colors.grey,
                    alignment: Alignment.center,
                    child: CircularProgressIndicator(),
                  ),
            SizedBox(height: 10),
            ElevatedButton(
              onPressed: () => _bytesPagKey.currentState?.start(),
              child: Text('播放二进制动画'),
            ),

            // 4. 交互式动画示例
            SizedBox(height: 30),
            Text('\n4. 交互式动画示例', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
            SizedBox(height: 10),
            GestureDetector(
              onTapDown: (details) async {
                List<String> layers = await _localPagKey.currentState?.getLayersUnderPoint(
                  details.localPosition.dx,
                  details.localPosition.dy,
                ) ?? [];
                if (layers.isNotEmpty) {
                  ScaffoldMessenger.of(context).showSnackBar(
                    SnackBar(content: Text('点击了图层:${layers.first}')),
                  );
                }
              },
              child: PAGView.asset(
                'assets/interactive_animation.pag',
                width: 300,
                height: 300,
                repeatCount: PAGView.REPEAT_COUNT_LOOP,
                autoPlay: true,
              ),
            ),
            Text('点击动画查看图层信息', style: TextStyle(fontSize: 12, color: Colors.grey)),
          ],
        ),
      ),
    );
  }
}

五、总结

flutter-pag插件为Flutter开发者提供了在OpenHarmony平台上集成PAG动画的便捷方式,具有以下优势:

  1. 易用性:提供简洁的API和丰富的示例,降低集成难度
  2. 全面性:支持多种PAG动画加载方式和完整的控制功能
  3. 高性能:针对OpenHarmony平台进行了专门优化,确保流畅的动画体验
  4. 可扩展性:支持自定义占位组件和事件监听,满足多样化需求
  5. 交互性:支持图层检测,可实现复杂的交互式动画效果

通过本文的介绍,您应该已经掌握了flutter-pag插件在OpenHarmony平台上的基本使用方法。无论是简单的动画展示还是复杂的交互式动画应用,flutter-pag都能为您提供强大的支持。

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐