如何通过很多张图片,实现执行手势播放动画

164 阅读2分钟

需求内容

需要通过很多张图片模拟3d滑动旋转展示模型

需求分析

拆分需求过后,就是通过监听手势,播放帧动画模拟3d效果。帧动画我的理解就是快速切换图片,让人眼看起来像是播放了一个视频的效果~

功能拆分

  1. 实现手势监听
  2. 实现图片无感知切换

手势监听

这边我们用到了flutter的GestureDetector组件,通过onPanUpdate方法获取手势滑动x轴偏移量。

图片无感知切换

这里无感知是关键点,我这边调研过程中对比了几个方案

图片展示方案结果
通过state控制图片展示渲染过程会造成白屏卡顿
通过设置图片属性解决白屏问题慢滑过程中没有问题,快速滑动由于flutter组件内部调用滑动函数时机为快速滑动后一次调用多个,造成图片内容切换过快,白屏图片忽略,无法展示动画效果
帧动画帧动画需将index和帧动画展示时机想关联无法获取滑动距离,同时也无法避免渲染卡顿风险
所有图片加载完成后,通过visible控制显隐还是有渲染过程,滑动不流畅
最终方案:用层级组件渲染所有图片并通过index将展示图片层级放在最上面动画过程比较流畅

实现方案

  1. 通过触摸组件动态监听滑动轨迹实现图片索引切换
  2. 用层级组件渲染所有图片并通过index将展示图片层级放在最上面(解决通过visible控制显示隐藏的卡顿问题)

代码实现

import 'package:flutter/material.dart';

class RotateImagePage extends StatefulWidget {
  const RotateImagePage({super.key});
  @override
  SBasePageState<RotateImagePage> createState() => _RotateImagePage();
}

class _RotateImagePage extends xxx
    with SingleTickerProviderStateMixin {
  //手指按下的位置
  double _down = 0.0;
  var index = 0;
  @override
  Widget? content(BuildContext context) {
    return GestureDetector(
        onPanEnd: (e) {
          _down = 0;
        },
        //手指滑动时会触发此回调
        onPanUpdate: (DragUpdateDetails e) {
          if (e.delta.dx > 0) {
            //手指移动的距离
            _down = _down + e.delta.dx;
            if (_down > 15) {
              setState(() {
                index = index <= 0 ? 72 : index - 1;
              });
              _down = 0;
            }
          } else {
            _down = _down + e.delta.dx;
            if (_down < -15) {
              setState(() {
                index = index >= 72 ? 0 : index + 1;
              });
              _down = 0;
            }
          } //用户手指滑动时,更新偏移,重新构建w
        },
        child: IndexedStack(
          index: index,
          children: [
            ...List.generate(
                73,
                (i) => Image.network(
                      '图片url${i < 10 ? '0$i' : '$i'}.jpg',
                    ))
          ],
        ));
  }
}