mirror of
https://github.com/bggRGjQaUbCoE/PiliPlus.git
synced 2026-04-21 03:15:14 +08:00
opt: matrix anim (#1829)
This commit is contained in:
committed by
GitHub
parent
4ac855d393
commit
8234b7ac92
@@ -1,5 +1,8 @@
|
||||
import 'dart:ui' as ui;
|
||||
|
||||
import 'package:PiliPlus/common/widgets/interactiveviewer_gallery/interactive_viewer.dart'
|
||||
as custom;
|
||||
import 'package:PiliPlus/common/widgets/only_layout_widget.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
/// https://github.com/qq326646683/interactiveviewer_gallery
|
||||
@@ -53,15 +56,16 @@ class InteractiveViewerBoundary extends StatefulWidget {
|
||||
|
||||
class InteractiveViewerBoundaryState extends State<InteractiveViewerBoundary>
|
||||
with SingleTickerProviderStateMixin {
|
||||
late TransformationController _controller;
|
||||
late AnimationController _animateController;
|
||||
late Animation<Offset> _slideAnimation;
|
||||
late Animation<double> _scaleAnimation;
|
||||
late Animation<Decoration> _opacityAnimation;
|
||||
late final TransformationController _controller;
|
||||
late final AnimationController _animateController;
|
||||
late final Animation<Decoration> _opacityAnimation;
|
||||
double dx = 0, dy = 0;
|
||||
|
||||
Offset _offset = Offset.zero;
|
||||
bool _dragging = false;
|
||||
|
||||
late Size _size;
|
||||
|
||||
bool get _isActive => _dragging || _animateController.isAnimating;
|
||||
|
||||
@override
|
||||
@@ -74,35 +78,42 @@ class InteractiveViewerBoundaryState extends State<InteractiveViewerBoundary>
|
||||
vsync: this,
|
||||
);
|
||||
|
||||
_updateMoveAnimation();
|
||||
|
||||
_scaleAnimation = _animateController.drive(
|
||||
Tween<double>(begin: 1.0, end: 0.25),
|
||||
);
|
||||
|
||||
_opacityAnimation = _animateController.drive(
|
||||
DecorationTween(
|
||||
begin: const BoxDecoration(color: Colors.black),
|
||||
end: const BoxDecoration(color: Colors.transparent),
|
||||
),
|
||||
);
|
||||
|
||||
_animateController.addListener(_updateTransformation);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_animateController.dispose();
|
||||
super.dispose();
|
||||
void _updateTransformation() {
|
||||
final val = _animateController.value;
|
||||
final scale = ui.lerpDouble(1.0, 0.25, val)!;
|
||||
|
||||
// Matrix4.identity()
|
||||
// ..translateByDouble(size.width / 2, size.height / 2, 0, 1)
|
||||
// ..translateByDouble(size.width * val * dx, size.height * val * dy, 0, 1)
|
||||
// ..scaleByDouble(scale, scale, 1, 1)
|
||||
// ..translateByDouble(-size.width / 2, -size.height / 2, 0, 1);
|
||||
|
||||
final tmp = (1.0 - scale) / 2.0;
|
||||
_controller.value = Matrix4.diagonal3Values(scale, scale, scale)
|
||||
..setTranslationRaw(
|
||||
_size.width * (val * dx + tmp),
|
||||
_size.height * (val * dy + tmp),
|
||||
0,
|
||||
);
|
||||
}
|
||||
|
||||
void _updateMoveAnimation() {
|
||||
final double endX = _offset.dx.sign * (_offset.dx.abs() / _offset.dy.abs());
|
||||
final double endY = _offset.dy.sign;
|
||||
_slideAnimation = _animateController.drive(
|
||||
Tween<Offset>(
|
||||
begin: Offset.zero,
|
||||
end: Offset(endX, endY),
|
||||
),
|
||||
);
|
||||
dy = _offset.dy.sign;
|
||||
if (dy == 0) {
|
||||
dx = 0;
|
||||
} else {
|
||||
dx = _offset.dx / _offset.dy.abs();
|
||||
}
|
||||
}
|
||||
|
||||
void _handleDragStart(ScaleStartDetails details) {
|
||||
@@ -114,7 +125,7 @@ class InteractiveViewerBoundaryState extends State<InteractiveViewerBoundary>
|
||||
_offset = Offset.zero;
|
||||
_animateController.value = 0.0;
|
||||
}
|
||||
setState(_updateMoveAnimation);
|
||||
_updateMoveAnimation();
|
||||
}
|
||||
|
||||
void _handleDragUpdate(ScaleUpdateDetails details) {
|
||||
@@ -123,11 +134,10 @@ class InteractiveViewerBoundaryState extends State<InteractiveViewerBoundary>
|
||||
}
|
||||
|
||||
_offset += details.focalPointDelta;
|
||||
|
||||
setState(_updateMoveAnimation);
|
||||
_updateMoveAnimation();
|
||||
|
||||
if (!_animateController.isAnimating) {
|
||||
_animateController.value = _offset.dy.abs() / context.size!.height;
|
||||
_animateController.value = _offset.dy.abs() / _size.height;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -153,29 +163,32 @@ class InteractiveViewerBoundaryState extends State<InteractiveViewerBoundary>
|
||||
}
|
||||
}
|
||||
|
||||
Widget get content => DecoratedBoxTransition(
|
||||
decoration: _opacityAnimation,
|
||||
child: SlideTransition(
|
||||
position: _slideAnimation,
|
||||
child: ScaleTransition(
|
||||
scale: _scaleAnimation,
|
||||
child: widget.child,
|
||||
),
|
||||
),
|
||||
);
|
||||
@override
|
||||
void dispose() {
|
||||
_animateController
|
||||
..removeListener(_updateTransformation)
|
||||
..dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return custom.InteractiveViewer(
|
||||
maxScale: widget.maxScale,
|
||||
minScale: widget.minScale,
|
||||
transformationController: _controller,
|
||||
onPanStart: _handleDragStart,
|
||||
onPanUpdate: _handleDragUpdate,
|
||||
onPanEnd: _handleDragEnd,
|
||||
onInteractionEnd: widget.onInteractionEnd,
|
||||
isAnimating: () => _animateController.value != 0,
|
||||
child: content,
|
||||
return LayoutSizeWidget(
|
||||
onPerformLayout: (size) => _size = size,
|
||||
child: DecoratedBoxTransition(
|
||||
decoration: _opacityAnimation,
|
||||
child: custom.InteractiveViewer(
|
||||
maxScale: widget.maxScale,
|
||||
minScale: widget.minScale,
|
||||
transformationController: _controller,
|
||||
onPanStart: _handleDragStart,
|
||||
onPanUpdate: _handleDragUpdate,
|
||||
onPanEnd: _handleDragEnd,
|
||||
onInteractionEnd: widget.onInteractionEnd,
|
||||
isAnimating: () => _animateController.value != 0,
|
||||
child: widget.child,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user