16
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【はじめてのRive】Flutterに2Dアニメーションスプラッシュスクリーンを導入する手順

Last updated at Posted at 2020-08-12

追記 2021.3.6

Rive2 が公開されたのに伴い、旧Rive のURLが変わりました。
本記事は、旧Rive について記述してものになりますので、ご了承ください。

概要

起動時にアニメーションがあるアプリって、なんかカッコいいですよねっ。

Flutterアプリケーションには、Riveで作成した2Dアニメーションをスプラッシュスクリーンとして組み込むという選択肢があります。

この記事では、はじめてRiveにふれる方向けの簡単な2Dアニメーションの作り方と、それをスプラッシュスクリーンとしての組み込む手順を紹介します。

ざっくりいうと・・・

  • アプリローディング中はAndroid/iOSネイティブのスプラッシュスクリーンの仕掛けを使います。この記事ではflutter_native_splashプラグインを使った方法を紹介します。
  • アプリローディング後の初期画面としてRiveで作成した2Dアニメーションを組み込みます。組み込みにはflare_flutterプラグインを使用します。
  • 画面遷移の実装は、Navigatorを使用しました。
  • ページ遷移のイメージはこんな感じです:
    page transition.png

この記事の検証に使ったリソース

Riveの作品。Forkして改変することも含め、自由に使っていただくことができますので、必要に合わせてご利用ください。

Flutterのソースコード。こちらも改変することも含め、自由に使っていただくことができますので、必要に合わせてご利用ください。

環境

バージョン

  • Flutter 1.20.1

プロジェクト設定

  • この記事では、FlutterプロジェクトのUse androidx.* artifactsONに設定して検証しました。

本編

1) Riveで2Dアニメーションを作成する

Riveにアクセスます。アカウントがない場合は作成しましょう。無料アカウントの場合、作成した作品の公開レベルがpublicとなりますが、私の場合はそれ以外特に困ることはありませんでした。

サインインすると、Explorerのページが表示され、公開されている作品を見ることができます。また、これら作品は「OPEN IN RIVE」ボタンを押せば『どのように作られているのか』を見ることもできますし、許可されていればForkもできます。

しかし数が多いので、もし参考になる作品を探したいならば、以下のチュートリアルページの動画を順にみていくことをお勧めします。動画に登場するアニメーションもExplorerページで公開されているので、あなたの最初の教科書になるはずです。
Tutorials - Rive

ではさっそくアニメーションを作ってみましょう。

Your Filesボタンをクリックし、+アイコンをクリックし、Flareを選択します。
File Propertiesのページで公開範囲を選択(無料ならPublicを選択)し、SAVEボタンをクリック。

するとまっさらなArtboardが表示されます。左上にはNew File 1との表示と、DESIGN/ANIMATEのページを切り替えるスイッチがありますね。

さて、ここからアニメーションを編集していくわけですが、その流れをざくっり説明すると、以下のようになります。

a. DESIGNページで、パーツの大きさ、配置、エフェクトなどプロパティ値を編集しデザインする。これがアニメーション編集時の「初期値」になります。
b. ANIMATIONページで、タイムラインのフレーム毎のパーツのプロパティ値を決める。「初期値」に対する変化をつけていくイメージです。

ではまず左上の作品のタイトルNew File 1を編集して、そうですね、app_splashとでもしておきましょう。
次に、アニメーションを作っていきましょう

1-a) アニメーションのパーツをデザインする

DESIGNページではArtboardのサイズを決めたり、左上のメニューからパーツの選択動作を切り替えたり、図形を呼び出したりすることができます。なお複雑な動きを行うためのBoneNodeもここから呼び出せますが、この記事ではそこまでやりません。

ではまずArtboardのサイズを決めます。画面左側のHIERARCHYに見えているArtboardを選択すると、画面右側にArtboardのプロパティが表示されるので、Sizeプロパティを変更してみましょう。私はxhdpiに合わせて WIDTH:720, HEIGHT:1280 としました。

次に図形を配置します。コツを少しだけまとめると、、、

  • Artboard全体の拡大縮小はマウスホイール。
  • Artboard全体の移動はスペースキーを押しながらドラッグ。
  • 別途用意した画像を利用する場合は、画面左下のASSETSにファイルをドラッグ&ドロップで登録してから、Artboardに配置する。

私は図形だけを使って次のようにしてみました。
コメント 2020-08-12 132548.png

星の図形を黄色に塗りつぶし、その周りにCorner Radiusプロパティで角を削った四角を、45度ごとにRotateして配置したものです。
ではこれを下地にして、アニメーションを作っていきます。

1-b) アニメーションを作る

ANIMATEページに切り替えてみましょう。画面左下にANIMATIONS、画面中央下部に再生ボタンや00:00:00、その右にはFPS00:10:00が表示されていますね。

最初に、アニメーション全体の設定を行います。

  • ANIMATIONSUntitledを右クリックし、Renameを行いましょう。今回は1本のアニメーションとしてスプラッシュアニメーションを作るつもりなので、名前はallとしました。
  • 画面中央下部のパネルの右上、FPSの値を変更しましょう。1秒当たりのフレーム数です。初期値の60は多いかな・・・私は12にしました。
  • 次にアニメーション全体の時間の長さを設定します。画面中央下部のパネルの右上、初期値は00:10:00(10秒と0フレーム)。私は00:03:00(3秒と0フレーム)にしました。書式がMM:ss:フレーム数である点に注意してください。

すると画面中央下部のタイムラインの時間軸が以下のように変わります。
コメント 2020-08-12 134053.png

あとはこの時間軸の各フレームごとに、パーツのプロパティ値の変化を作っていく作業になります。ただしパーツのプロパティ値は、例えば「1フレームで0.0, 5フレームで1.0」に固定すると、「2~4フレームでは0.2, 0.4, 0.6, 0.8」というようにプロパティ値が自動計算されるので、作業は「時点毎のプロパティ値を固定していく作業」の繰り返しです。「固定」するためにはプロパティ値の右にあるにします。

例えば私の「星」に対する作業の流れをまとめると・・・

0フレーム: 星のScale: 0, 0
12フレーム: 星のScale: 1.2, 1.2
14フレーム: 星のScale: 1.0, 1.0

です。しかしこれだけだとやや単調な動き・・・。そこでタイムラインの「星」の行を選択し、画面右側のプロパティの一番したKEY INTERPOLATIONTypeLinerからCubicに変えてみましょう。するとどうでしょう・・・生き生きしましたね!(語彙力...
コメント 2020-08-12 132548.gif

星の周りの四角に対するアニメーションもつけてみました。1~4直角に対して、45度の四角をやや遅れて出しています。えぇ、チュートリアルにあるデザインのパクリ(劣化版)ですね!
コメント 2020-08-12 132549.gif

他、DESIGNページに戻ってEFFECTSを足し、ぼかしBlurや影Drop Shaddowの変化をつけるとそれなりの見た目になっていきますが、本題から逸れるので、これくらいにしておきます。

ではこのアニメーションをFlutterで取り込める形式で保存しましょう。画面右上の出力アイコンからExportを選択します。FormatはBinary。Duration from Last KeyframeをONにすると、最後にプロパティを固定したフレーム以降を切り捨てることができます。EXPORTボタンをクリックすると、app_splash.flrファイルがダウンロードされます。

では次に、Flutterの実装を行いましょう。

2) Navigatorによるページ遷移を実装する

Navigatorの説明は省略します。ページ遷移はmain.dartに定義します。以下のような実装になります。

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

import 'view/app_splash_page.dart';
import 'view/my_home_page.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Flare Splash-screen Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      routes: <String, WidgetBuilder>{
        '/': (_) => AppSplashPage(),
        '/home': (_) => MyHomePage(title: 'Flutter Demo'),
      },
    );
  }
}
  • AppSplashPageは初期画面であり、アニメーションスプラッシュViewにあたる部分を指します。この後で作ります。
  • MyHomePageはホーム画面を指します。ホーム画面はFlutterのサンプル実装でも構いませんが、ホーム画面からスプラッシュ画面への逆行を防ぐため、ホーム画面のルート位置にWidgetWillPopScopeを配置する必要があります。
  @override
  Widget build(BuildContext context) {
    return WillPopScope(
      onWillPop: () async => false,
      child: Scaffold(
        appBar: AppBar(
          ...(省略)...

3) 初期画面を作成し、Riveで作成した2Dアニメーション(*.flr)を組み込む。

pubspec.yamlにflutter_flareをインストールします。

pubspec.yaml
dependencies:
  flutter:
    sdk: flutter
  flare_flutter: ^2.0.5

pubspec.yamlに、Riveで作成する2Dアニメーション(*.flr)をassetsとして登録するための定義を追加します。
※ここでは/assetsディレクトリに置いたものすべてを認識する例にしています。

pubspec.yaml
flutter:
  assets:
    - assets/

Riveで作成した2Dアニメーション(*.flr)をassets/ディレクトリに配置します。

AppSplashPageを実装します。Riveで作成した2Dアニメーション(*.flr)の組み込みは、以下のような実装になります。

view/app_splash_page.dart
import 'package:flare_flutter/flare_actor.dart';
import 'package:flutter/material.dart';

class AppSplashPage extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => _AppSplashPageState();
}

class _AppSplashPageState extends State<AppSplashPage>{

  @override
  Widget build(BuildContext context) {
    return WillPopScope(
        onWillPop: () async => false,
        child: Container(
          width: double.infinity,
          height: double.infinity,
          color: Colors.blueAccent,
          child: FlareActor(
          'assets/app_splash.flr',
          alignment: Alignment.center,
          fit: BoxFit.contain,
          animation: 'all',
          callback: (name) {
            Navigator.of(context).pushReplacementNamed("/home");
          },
        )
      )
    );
  }
}
  • Riveで作成した2Dアニメーション(*.flr)は、Widget FlareActorを使って組み込みます。
  • 引数 animationで、再生するアニメーション名を指定します。
  • 引数 callbackで、アニメーション終了後の処理を記述することができます。ここでは、ホーム画面への遷移を指定します。
  • ホーム画面への遷移は、メソッド pushReplacementNamedを使用して、ホーム画面からスプラッシュ画面への逆行を防ぎます。
  • Widget WillPopScopeを指定することで、AndroidのBackボタンによって画面遷移の逆行が起きる問題を防ぎます。
  • FlareActorを囲うContainerは、背景色を指定するためのものです。

ここまでを一度、デバイスで動作させてみましょう。
以下、リリースビルドして動作させた結果です。

flutter run --release

コメント 2020-08-12 132550.gif

スプラッシュアニメーションからホーム画面への遷移はスムーズにできましたね!
しかしスプラッシュアニメーションの前に白い画面が見えるのがダサいです。この部分が、私がローディング画面と呼んでいる部分。ネイティブスプラッシュスクリーンを設定することで差し替えましょう。

4) ネイティブスプラッシュスクリーンを設定する。

ネイティブスプラッシュスクリーンとして表示する画像を用意し、assets/app_splash.pngに保存します。
私は720*1280のサイズで、中央に白い★がある透過PNGを保存しました。

次に、Flutterアプリケーションにflutter_native_splashプラグインを組み込みます。

pubspec.yaml
dependencies:
  flutter:
    sdk: flutter
  flare_flutter: ^2.0.5
  flutter_native_splash: ^0.1.9

さらにflutter_native_splashプラグイン用の設定を追記します。

  • imageは表示する画像です。
  • colorは背景色です。私はアニメーションに指定した背景色blueAccentと同じ色"448AFF"にしてみました。
pubspec.yaml
flutter_native_splash:
  image: assets/app_splash.png
  color: "448AFF"

pubspec.yamlを保存したら、次のコマンドを実行。するとiOSとAndroid向けにスプラッシュスクリーンが設定されます。

flutter pub get
flutter pub pub run flutter_native_splash:create

ではデバイスで動作させてみましょう。
以下、リリースビルドして動作させた結果です。

flutter run --release

コメント 2020-08-12 132551.gif

ダサい白の画面がなくなって、ほら、いい感じ!(語彙力...

あと、デザインが致命的にアレな点はお許しください。。。

最後に

私はプログラマーですが、プログラマーでもそれなりにアニメーションが作れちゃうという点で「Riveは面白いなーっ」て思いました。Flutterはプログラミング経験の浅い人でもクロスプラットフォームに対応するアプリを短期間で作ることができる素晴らしいフレームワークだと感じているので、ぜひそこにRiveで作った2Dアニメーションも導入してもらって、より多くの人にアプリ開発ライフをより楽しんでもらえたらいいな、そんな想いでこの記事をまとめました。

この記事が1人でも多くの方の助けになれば幸いです。


(2020/8/13 追記)

続編の記事を公開しました。

16
10
6

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
16
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?