更新快检报告
This commit is contained in:
92
lib/pages/device/component/SpeedControlledGif.dart
Normal file
92
lib/pages/device/component/SpeedControlledGif.dart
Normal file
@@ -0,0 +1,92 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'dart:ui' as ui;
|
||||
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
class SpeedControlledGif extends StatefulWidget {
|
||||
final String assetPath;
|
||||
final double speedFactor;
|
||||
final BoxFit? fit;
|
||||
|
||||
/// [speedFactor] 播放速度倍数,默认1.0,
|
||||
/// 大于1表示加速播放,小于1表示减速播放
|
||||
const SpeedControlledGif(
|
||||
this.assetPath, {
|
||||
Key? key,
|
||||
this.speedFactor = 1.0,
|
||||
this.fit,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
_SpeedControlledGifState createState() => _SpeedControlledGifState();
|
||||
}
|
||||
|
||||
class _SpeedControlledGifState extends State<SpeedControlledGif> {
|
||||
ui.Codec? _codec;
|
||||
ui.FrameInfo? _currentFrame;
|
||||
Timer? _timer;
|
||||
bool _isDisposed = false;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_loadGif();
|
||||
}
|
||||
|
||||
Future<void> _loadGif() async {
|
||||
final data = await rootBundle.load(widget.assetPath);
|
||||
_codec = await ui.instantiateImageCodec(data.buffer.asUint8List());
|
||||
|
||||
if (_isDisposed) return;
|
||||
|
||||
_showNextFrame();
|
||||
}
|
||||
|
||||
Future<void> _showNextFrame() async {
|
||||
if (_isDisposed || _codec == null) return;
|
||||
|
||||
_currentFrame = await _codec!.getNextFrame();
|
||||
|
||||
if (_isDisposed) return;
|
||||
|
||||
if (mounted) {
|
||||
setState(() {});
|
||||
}
|
||||
|
||||
// 取当前帧持续时间,单位毫秒
|
||||
final baseDuration = _currentFrame?.duration.inMilliseconds ?? 100;
|
||||
|
||||
// 限制最小帧间隔,防止刷新过快
|
||||
const minFrameDuration = 50;
|
||||
|
||||
// 计算实际播放帧间隔,speedFactor越大速度越快
|
||||
final adjustedDuration = (baseDuration / widget.speedFactor)
|
||||
.round()
|
||||
.clamp(minFrameDuration, 10000);
|
||||
|
||||
_timer = Timer(Duration(milliseconds: adjustedDuration), _showNextFrame);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_isDisposed = true;
|
||||
_timer?.cancel();
|
||||
_codec?.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (_currentFrame == null) {
|
||||
// 加载中或无帧时显示空容器或占位
|
||||
return Container();
|
||||
}
|
||||
return RawImage(
|
||||
image: _currentFrame!.image,
|
||||
fit: widget.fit,
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user