Flutterで画像を現実のカードを裏返すみたいに裏返して、別の画像を表示するという実装をしました。
画像を180度回転させたり、反転させたりというのは簡単にできますが、裏返すというのはある程度工夫しないと実現できません。
独自のWidgetを作成することで実現しているので、サンプルコードと共にご紹介します。
画像を裏返して別の画像を表示するイメージ
今回は、Flutterで画像を現実のカードを裏返すみたいに裏返して、別の画像を表示するという実装をしました。
言葉だと伝わりづらいのでイメージを貼ってみました。
このようなものを実装したので、紹介していきます。
ちなみにこのような動きのことを英語で「flip」というそうです。
調査する際に少し苦労しました。
画像を裏返して別の画像を表示する実装
今回は裏返して別の画像を表示するWidgetを作成しました。
以下のような仕様のWidgetになりました。
- 初期表示時の画像パスを渡す(画像1)
- 裏返したときに表示する画像のパスに入れ替える(画像2)
- 画像1が裏返るアニメーションをしたあと、画像2を表示する
実際のソースコードは以下のとおりです。
import 'dart:math';
import 'package:flutter/material.dart';
class FlipImg extends StatefulWidget {
final String assetPath;
const FlipImg({Key? key, required this.assetPath}) : super(key: key);
@override
_FlipImgState createState() => _FlipImgState();
}
class _FlipImgState extends State<FlipImg>
with SingleTickerProviderStateMixin {
late String _currentImagePath;
late String _image1;
late String _image2;
late AnimationController _animationController;
final Curve _rotationCurve = Curves.elasticOut;
double _rotation = 0.0;
@override
void initState() {
super.initState();
_image1 = widget.assetPath;
_currentImagePath = widget.assetPath;
_animationController = AnimationController(
vsync: this,
duration: const Duration(milliseconds: 3800),
)
..addListener(_updateRotation)
..addStatusListener((status) {
if (status == AnimationStatus.completed) {
_onRotationComplete();
}
});
}
@override
void didUpdateWidget(covariant FlippingImage oldWidget) {
super.didUpdateWidget(oldWidget);
if (widget.assetPath != oldWidget.assetPath) {
_immediatelyFinishCurrentAnimation();
_image2 = widget.assetPath;
_flipCard();
}
}
void _flipCard() {
_currentImagePath = _image1;
_animationController.forward(from: 0.0);
}
void _immediatelyFinishCurrentAnimation() {
if (_animationController.isAnimating) {
_animationController.stop();
_currentImagePath = _image2;
_image1 = _image2;
}
}
void _onRotationComplete() {
setState(() {
_animationController.value = 0;
_image1 = _image2;
_currentImagePath = _image2;
});
}
@override
void dispose() {
_animationController.dispose();
super.dispose();
}
void _updateRotation() {
setState(() {
_rotation = pi * _rotationCurve.transform(_animationController.value);
if (_currentImagePath == _image1 && _rotation > pi / 2) {
_currentImagePath = _image2;
} else if (_currentImagePath == _image2 && _rotation < pi / 2) {
_currentImagePath = _image1;
} else if (_currentImagePath == _image2) {
_rotation = _rotation - pi;
}
});
}
@override
Widget build(BuildContext context) {
return Container(
child: Center(
child: Transform(
transform: Matrix4.identity()
..setEntry(3, 2, 0.001)
..rotateY(_rotation),
alignment: FractionalOffset.center,
child: ClipRRect(
borderRadius: BorderRadius.circular(16),
child: IntrinsicHeight(
child: Image.asset(
_currentImagePath,
),
),
),
),
),
);
}
}
かなりいい感じです。
まとめ
Flutterのアニメーションを駆使して、画像が裏返っているような動きを実現しました。
アニメーションは慣れないと難しいですが、使いこなせるとかなりいい感じの動きを見せることができそうです。
Flutter学習情報
Flutterを勉強するのに最適な参考書は、以下の「基礎から学ぶFlutter」です。
環境構築から、Dart/Flutterの基本/テストやパフォーマンスチューニングまで一通り学ぶことができます。
また、当ブログではFlutterを初心者が学ぶためにオススメな方法を「Flutter を初心者が学ぶおすすめの勉強法!【間違いない動画があります】」という記事で公開していますので、Flutterに興味がある方は是非読んでみてください。
動画学習がしたい!という方にオススメの記事がこちらです。
Flutterの将来性はどうなのか?をまとめた記事はこちらです。