ベータコンピューティングの活動や技術、開発のこだわりなどを紹介するブログです。



Flutterでパズルを作ってみた話

弊社Android・クロスプラットフォーム担当のd-ariakeです。

弊社でもクロスプラットフォーム開発においてFlutterを採用しています。
今回はFlutter for Webでシンプルなパズルを作ってみたので、紹介させていただこうと思います。

作ったもの

このようなパズルを作ってみました。

flutter_puzzle

GitHub Pagesに置いてあります。
ぜひ遊んでみてください。
https://betacomputing.github.io/flutter_puzzle/

ソースコードはこちらに置いてあります。
https://github.com/BetaComputing/flutter_puzzle

Flutter for Webについて

3/4に Flutter 2.0 がリリースされましたが、その際にFlutterのWebサポートがstable化しました。
私もなにかFlutterでWebアプリを作ってみたいと思ったので、さっそくこのパズルを作ってみました。

特に手動で有効化設定を行わずともWebサポートが有効化されているので、

flutter create --org jp.co.betacomputing --platforms web ./flutter_puzzle

といったコマンドでWeb用のFlutterプロジェクトが作成することができます。

Webアプリ用ビルドは

flutter build web --web-renderer html

というコマンドで行うことができます。

上記ビルドコマンドにもオプションとして指定していますが、Flutter for Webには htmlcanvaskit の2通りのレンダリング方式があります。
それぞれダウンロードサイズの削減・他プラットフォームとの互換性とパフォーマンス性というメリットがあるようです。

ですが、現状はCanvasKitによるレンダリングにおいて正しく文字列が描画されないというバグがあるようなので、 --web-renderer html を指定したほうが良さそうです。

参考:

スライドアニメーションについて

このパズルを遊んでもらうとわかると思いますが、ピースを選択するとスライドアニメーションが再生されるようになっています。
これは AnimatedPadding を利用して実現させています。

パズルのピースを配置するコード は以下のとおりです。
各ピースの左と上のパディングを設定することによって任意の位置に配置するという実装アプローチを取っています。

//  パズルの複数のピースを生成する。
Widget _buildPieces(double pieceWidth, double pieceHeight) {
  return Stack(
    children: puzzle.pieces.map(
      (piece) {
        final offsetX = pieceWidth * piece.currentPos.hIndex;
        final offsetY = pieceHeight * piece.currentPos.vIndex;

        return AnimatedPadding(
          padding: EdgeInsets.only(left: offsetX, top: offsetY),
          duration: animDuration,
          child: SizedBox(
            width: pieceWidth,
            height: pieceHeight,
            child: _buildPiece(piece),
          ),
        );
      },
    ).toList(),
  );
}

あるピースがクリックされ、1つ右のマスに移動する状況を考えます。
右に移動するため、水平方向のインデックス piece.currentPos.hIndex の値が + 1 されます。
すると、 EdgeInsets.only()left には、更新前の値 offsetX よりも pieceWidth 分だけ大きな値が指定されます。
ここで AnimatedPadding を利用しているので、更新前と更新後の左パディングの値を線形補間しながら、なめらかに表示されるように描画してくれます。

更新後の値を渡すだけで、アニメーションの途中経過の面倒な座標計算を一切せずとも、Flutterが自動的にいい感じにしてくれました。 🙌

参考:

GitHub Pagesについて

最後にビルドとデプロイに関して軽く説明します。

見ての通り、このパズルはGitHub Pagesに配置しています。
タグをプッシュすると自動的にビルドが走り、ビルド内容が gh-pages ブランチにコミットされるように設定しました。

Release.yml:

  - name: Build (Web)
    run: flutter build web --web-renderer html

  - name: Deploy
    uses: peaceiris/actions-gh-pages@v3
    with:
      github_token: ${{ secrets.GITHUB_TOKEN }}
      publish_dir: ./build/web

gh-pages ブランチへの配置には peaceiris/actions-gh-pages@v3 というactionを利用しています。 GitHubのトークンとビルド先のディレクトリと指定するだけで、自動的にいい感じにしてくれます。 🙌

FlutterとGitHub Pagesを使えば、こんなに簡単にWebアプリが作れちゃいました。
今後も簡単なWebアプリであればFlutterで作ってみようと思います。 😤

おわりに

Beta Computing株式会社は石川県のスマートフォンアプリ開発に特化したソフトウェア会社です。 Kotlin・Swiftによるスマホアプリ開発も、FlutterやXamarin.Forms、Unityによるクロスプラットフォームのスマホアプリ開発も、得意としているスマホアプリ開発のプロフェッショナルです。

スマホアプリ開発をご検討されているのでしたら、是非私たちBeta Computing株式会社におまかせください! 業種・ジャンル問わず対応可能ですので、ぜひご相談下さい。