Flutter開発実践 - CustomClipperによる長いピクチャフレームのアニメーション効果のトリミング
開発プロセスでは、フレーム アニメーションの各フレームが超長い画像上に表示されることがよくあり、このフレーム アニメーションの効果を処理する必要があります。ここではCustomClipperを使用しています
1.カスタムクリッパー
CustomClipper は Listenable から継承します
抽象クラス CustomClipper は Listenable を拡張します
CustomClipper サブクラスを実装してトリミング機能を実装します。
class PicCustomClipper extends CustomClipper<Rect> {
PicCustomClipper(this.rect);
Rect rect;
// Rect getClip(Size size) => Rect.fromLTWH(0.0, 15.0, 40.0, 30.0);
Rect getClip(Size size) => rect;
bool shouldReclip(CustomClipper<Rect> oldClipper) => true;
}
- getClip()は画像サイズが60×60なのでクリッピング領域を取得するインターフェースです。
- クリッピング領域を Rect.fromLTWH(10.0, 15.0, 40.0, 30.0) として返します。これは、画像の中央の 40×30 ピクセルの範囲です。
shouldReclip() インターフェースは、再クリップするかどうかを決定します。
アプリケーション内でクリッピング領域が決して変更されない場合は、再クリッピングがトリガーされず、不要なパフォーマンスのオーバーヘッドが回避されるように、 false を返す必要があります。
クリッピング領域が変更される場合 (クリッピング領域でアニメーションを実行するなど)、変更後に true を返してクリッピングを再実行する必要があります。
2. 再生フレームアニメーションを実現
CustomClipper は長い画像をカットした後、フレーム アニメーションの一貫した効果を実現するために、長い画像のさまざまな領域を一定の間隔で表示します。
class PicFrameAnim extends StatefulWidget {
const PicFrameAnim({
required this.size, required this.imageSize, Key? key})
: super(key: key);
final Size size;
final Size imageSize;
_PicFrameAnimState createState() => _PicFrameAnimState();
}
class _PicFrameAnimState extends State<PicFrameAnim>
with TickerProviderStateMixin {
late Duration _duration;
late int _imageIndex;
late int _currentIndex;
// 定义一个裁剪
late PicCustomClipper _clipper = PicCustomClipper(
Rect.fromLTWH(0.0, 0.0, widget.size.width, widget.size.height));
void initState() {
// TODO: implement initState
super.initState();
_duration = Duration(milliseconds: 200);
_imageIndex = 1;
_currentIndex = 0;
if (widget.size.height > 0) {
_imageIndex = (widget.imageSize.height / widget.size.height).floor();
}
if (_imageIndex >= 2) {
updateImage();
}
}
void updateImage() {
if (_currentIndex >= _imageIndex) {
_currentIndex = 0;
}
_clipper = PicCustomClipper(Rect.fromLTWH(
0.0,
_currentIndex * (widget.size.height),
widget.size.width,
widget.size.height));
_currentIndex++;
if (mounted) {
setState(() {
});
}
Future.delayed(_duration, () {
if (mounted) {
updateImage();
}
});
}
void dispose() {
// TODO: implement dispose
super.dispose();
}
Matrix4 buildMatrix4() {
double dx = 0;
double dy = 0;
///Y轴方向平移
dy = -_currentIndex * (widget.size.height) + (widget.size.height);
///在XOY平面的平移
return Matrix4.translationValues(dx, dy, 0);
}
Widget build(BuildContext context) {
return Container(
width: widget.imageSize.width,
height: widget.imageSize.height,
child: Transform(
///构建Matrix4
transform: buildMatrix4(),
///中心对齐
alignment: Alignment.center,
child: ClipRect(
clipper: _clipper,
child: buildBGArrow(context),
),
),
);
}
Widget buildBGPicImage(BuildContext context) {
return Image.network(
"https://avatars2.githubusercontent.com/u/20411648?s=460&v=4",
width: 100.0,
height: 300.0,
);
}
}
3. まとめ
Flutter 開発の実践 - CustomClipper で長いピクチャ フレームのアニメーション効果をトリミングします。
https://blog.csdn.net/gloryFlow/article/details/132253251
学習記録、日々進歩しています。