需求内容
需要通过很多张图片模拟3d滑动旋转展示模型
需求分析
拆分需求过后,就是通过监听手势,播放帧动画模拟3d效果。帧动画我的理解就是快速切换图片,让人眼看起来像是播放了一个视频的效果~
功能拆分
- 实现手势监听
- 实现图片无感知切换
手势监听
这边我们用到了flutter的GestureDetector组件,通过onPanUpdate方法获取手势滑动x轴偏移量。
图片无感知切换
这里无感知是关键点,我这边调研过程中对比了几个方案
| 图片展示方案 | 结果 |
|---|---|
| 通过state控制图片展示 | 渲染过程会造成白屏卡顿 |
| 通过设置图片属性解决白屏问题 | 慢滑过程中没有问题,快速滑动由于flutter组件内部调用滑动函数时机为快速滑动后一次调用多个,造成图片内容切换过快,白屏图片忽略,无法展示动画效果 |
| 帧动画 | 帧动画需将index和帧动画展示时机想关联无法获取滑动距离,同时也无法避免渲染卡顿风险 |
| 所有图片加载完成后,通过visible控制显隐 | 还是有渲染过程,滑动不流畅 |
| 最终方案:用层级组件渲染所有图片并通过index将展示图片层级放在最上面 | 动画过程比较流畅 |
实现方案
- 通过触摸组件动态监听滑动轨迹实现图片索引切换
- 用层级组件渲染所有图片并通过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',
))
],
));
}
}