Flutter development practice - CustomClipper cropping long picture frame animation effect
During the development process, it is often encountered that each frame of frame animation is displayed on a super long image, and this frame animation effect needs to be processed. I am using CustomClipper here
1. CustomClipper
CustomClipper inherits from Listenable
abstract class CustomClipper extends Listenable
We implement the CustomClipper subclass to implement the cropping function
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() is an interface used to obtain the clipping area, since the image size is 60×60,
- We return the clipping area as Rect.fromLTWH(10.0, 15.0, 40.0, 30.0), which is the range of 40×30 pixels in the middle of the picture.
The shouldReclip() interface decides whether to re-clip.
If the clipping area never changes in the application, false should be returned, so that re-clipping will not be triggered and unnecessary performance overhead will be avoided.
If the clipping area will change (such as performing an animation on the clipping area), it should return true after the change to re-execute the clipping.
2. Realize playback frame animation
After the CustomClipper cuts the long image, it displays different areas of the long image at regular intervals to achieve the coherent effect of the frame animation.
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. Summary
Flutter development practice-CustomClipper crops long picture frame animation effect.
https://blog.csdn.net/gloryFlow/article/details/132253251
learning records, making progress every day.