flutter开发实战-CustomClipper裁剪长图帧动画效果

flutter开发实战-CustomClipper裁剪长图帧动画效果

在开发过程中,经常遇到帧动画的每一帧图显示在超长图上,需要处理这种帧动画效果。我这里使用的是CustomClipper

一、CustomClipper

CustomClipper继承于Listenable

abstract class CustomClipper extends Listenable

我们实现CustomClipper子类来实现裁剪功能

dart 复制代码
class PicCustomClipper extends CustomClipper<Rect> {
  PicCustomClipper(this.rect);

  Rect rect;

  // Rect getClip(Size size) => Rect.fromLTWH(0.0, 15.0, 40.0, 30.0);

  @override
  Rect getClip(Size size) => rect;

  @override
  bool shouldReclip(CustomClipper<Rect> oldClipper) => true;
}
  • getClip()是用于获取剪裁区域的接口,由于图片大小是60×60,
  • 我们返回剪裁区域为Rect.fromLTWH(10.0, 15.0, 40.0, 30.0),即图片中部40×30像素的范围。
    shouldReclip() 接口决定是否重新剪裁。
    如果在应用中,剪裁区域始终不会发生变化时应该返回false,这样就不会触发重新剪裁,避免不必要的性能开销。
    如果剪裁区域会发生变化(比如在对剪裁区域执行一个动画),那么变化后应该返回true来重新执行剪裁。

二、实现播放帧动画

CustomClipper裁剪长图后,每隔一段时间展示长图的不同区域,实现帧动画的连贯效果。

dart 复制代码
class PicFrameAnim extends StatefulWidget {
  const PicFrameAnim({required this.size, required this.imageSize, Key? key})
      : super(key: key);

  final Size size;
  final Size imageSize;

  @override
  _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));

  @override
  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();
      }
    });
  }

  @override
  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);
  }

  @override
  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,
);
  }
}

三、小结

flutter开发实战-CustomClipper裁剪长图帧动画效果。
https://blog.csdn.net/gloryFlow/article/details/132253251

学习记录,每天不停进步。

相关推荐
c语言鹌鹑蛋35 分钟前
【进程间通信】--- 匿名管道,命名管道
linux
2501_9387900739 分钟前
从 0 到 1:解决 VsCode 远程连服务器后 Github Copilot 无法使用问题
服务器·vscode·github
江輕木44 分钟前
如何使用宿主机软件共享网络给CentOS 7
linux·运维·服务器
IT曙光1 小时前
在华为TaiShan 200系列服务器基于CentOS 7.6/7.7创建虚拟机
运维·服务器·centos
代码一天不写我浑森蓝廋1 小时前
CentOS7 使用 centos-release-scl-rh yum库安装 devtoolset
linux·centos·gcc·devtoolset
郁大锤1 小时前
conda虚拟环境占用空间太多,如何清理?
linux·conda
悢七1 小时前
windows npm打包无问题,但linux npm打包后部分样式缺失
linux·前端·npm
The Chosen One9851 小时前
【Linux】Linux下基本指令:man echo cp mv move less date grep zip tar 指令以及指令的本质
linux·运维·服务器
退役小学生呀2 小时前
二十二、DevOps:基于Tekton的云原生平台落地(三)
linux·云原生·容器·kubernetes·k8s·devops·tekton
君以思为故2 小时前
认识linux -- 编辑器vim以及编译器gcc/g++和Makefile文件
linux·编辑器·vim