mirror of
https://github.com/bggRGjQaUbCoE/PiliPlus.git
synced 2026-05-15 05:33:59 +08:00
improve player gesture
Signed-off-by: dom <githubaccount56556@proton.me>
This commit is contained in:
@@ -16,29 +16,30 @@ import 'package:vector_math/vector_math_64.dart' show Quad, Vector3;
|
|||||||
class MouseInteractiveViewer extends StatefulWidget {
|
class MouseInteractiveViewer extends StatefulWidget {
|
||||||
const MouseInteractiveViewer({
|
const MouseInteractiveViewer({
|
||||||
super.key,
|
super.key,
|
||||||
this.clipBehavior = Clip.hardEdge,
|
this.clipBehavior = .hardEdge,
|
||||||
this.panAxis = PanAxis.free,
|
this.panAxis = .free,
|
||||||
this.boundaryMargin = EdgeInsets.zero,
|
this.boundaryMargin = .zero,
|
||||||
this.constrained = true,
|
this.constrained = true,
|
||||||
this.maxScale = 2.5,
|
this.maxScale = 2.5,
|
||||||
this.minScale = 0.8,
|
this.minScale = 0.8,
|
||||||
this.interactionEndFrictionCoefficient = _kDrag,
|
this.interactionEndFrictionCoefficient = _kDrag,
|
||||||
this.pointerSignalFallback,
|
required this.pointerSignalFallback,
|
||||||
this.onPointerPanZoomUpdate,
|
this.onPointerPanZoomUpdate,
|
||||||
this.onPointerPanZoomEnd,
|
this.onPointerPanZoomEnd,
|
||||||
this.onPointerDown,
|
required this.onPointerDown,
|
||||||
this.onInteractionEnd,
|
required this.onPanEnd,
|
||||||
this.onInteractionStart,
|
required this.onPanStart,
|
||||||
this.onInteractionUpdate,
|
required this.onPanUpdate,
|
||||||
|
required this.onScaleUpdate,
|
||||||
this.panEnabled = true,
|
this.panEnabled = true,
|
||||||
this.scaleEnabled = true,
|
this.scaleEnabled = true,
|
||||||
this.scaleFactor = kDefaultMouseScrollToScaleFactor,
|
this.scaleFactor = kDefaultMouseScrollToScaleFactor,
|
||||||
this.transformationController,
|
required this.transformationController,
|
||||||
this.alignment,
|
this.alignment,
|
||||||
this.trackpadScrollCausesScale = false,
|
this.trackpadScrollCausesScale = false,
|
||||||
required this.childKey,
|
required this.childKey,
|
||||||
required this.child,
|
required this.child,
|
||||||
required this.onTranslate,
|
required this.scaleGestureRecognizer,
|
||||||
}) : assert(minScale > 0),
|
}) : assert(minScale > 0),
|
||||||
assert(interactionEndFrictionCoefficient > 0),
|
assert(interactionEndFrictionCoefficient > 0),
|
||||||
assert(maxScale > 0),
|
assert(maxScale > 0),
|
||||||
@@ -57,16 +58,17 @@ class MouseInteractiveViewer extends StatefulWidget {
|
|||||||
final double maxScale;
|
final double maxScale;
|
||||||
final double minScale;
|
final double minScale;
|
||||||
final double interactionEndFrictionCoefficient;
|
final double interactionEndFrictionCoefficient;
|
||||||
final PointerSignalEventListener? pointerSignalFallback;
|
final PointerSignalEventListener pointerSignalFallback;
|
||||||
final PointerPanZoomUpdateEventListener? onPointerPanZoomUpdate;
|
final PointerPanZoomUpdateEventListener? onPointerPanZoomUpdate;
|
||||||
final PointerPanZoomEndEventListener? onPointerPanZoomEnd;
|
final PointerPanZoomEndEventListener? onPointerPanZoomEnd;
|
||||||
final PointerDownEventListener? onPointerDown;
|
final PointerDownEventListener onPointerDown;
|
||||||
final GestureScaleEndCallback? onInteractionEnd;
|
final GestureScaleEndCallback onPanEnd;
|
||||||
final GestureScaleStartCallback? onInteractionStart;
|
final GestureScaleStartCallback onPanStart;
|
||||||
final GestureScaleUpdateCallback? onInteractionUpdate;
|
final GestureScaleUpdateCallback onPanUpdate;
|
||||||
final TransformationController? transformationController;
|
final ValueChanged<double> onScaleUpdate;
|
||||||
|
final TransformationController transformationController;
|
||||||
final GlobalKey childKey;
|
final GlobalKey childKey;
|
||||||
final VoidCallback onTranslate;
|
final ScaleGestureRecognizer scaleGestureRecognizer;
|
||||||
|
|
||||||
static const double _kDrag = 0.0000135;
|
static const double _kDrag = 0.0000135;
|
||||||
|
|
||||||
@@ -76,8 +78,7 @@ class MouseInteractiveViewer extends StatefulWidget {
|
|||||||
|
|
||||||
class _MouseInteractiveViewerState extends State<MouseInteractiveViewer>
|
class _MouseInteractiveViewerState extends State<MouseInteractiveViewer>
|
||||||
with TickerProviderStateMixin {
|
with TickerProviderStateMixin {
|
||||||
late TransformationController _transformer =
|
late TransformationController _transformer;
|
||||||
widget.transformationController ?? TransformationController();
|
|
||||||
|
|
||||||
final GlobalKey _parentKey = GlobalKey();
|
final GlobalKey _parentKey = GlobalKey();
|
||||||
Animation<Offset>? _animation;
|
Animation<Offset>? _animation;
|
||||||
@@ -234,6 +235,9 @@ class _MouseInteractiveViewerState extends State<MouseInteractiveViewer>
|
|||||||
widget.minScale,
|
widget.minScale,
|
||||||
widget.maxScale,
|
widget.maxScale,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
widget.onScaleUpdate(clampedTotalScale);
|
||||||
|
|
||||||
final double clampedScale = clampedTotalScale / currentScale;
|
final double clampedScale = clampedTotalScale / currentScale;
|
||||||
return matrix.clone()
|
return matrix.clone()
|
||||||
..scaleByDouble(clampedScale, clampedScale, clampedScale, 1);
|
..scaleByDouble(clampedScale, clampedScale, clampedScale, 1);
|
||||||
@@ -270,10 +274,15 @@ class _MouseInteractiveViewerState extends State<MouseInteractiveViewer>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool _isSinglePointer = false;
|
||||||
|
|
||||||
// Handle the start of a gesture. All of pan, scale, and rotate are handled
|
// Handle the start of a gesture. All of pan, scale, and rotate are handled
|
||||||
// with GestureDetector's scale gesture.
|
// with GestureDetector's scale gesture.
|
||||||
void _onScaleStart(ScaleStartDetails details) {
|
void _onScaleStart(ScaleStartDetails details) {
|
||||||
widget.onInteractionStart?.call(details);
|
if (_isSinglePointer = details.pointerCount == 1) {
|
||||||
|
widget.onPanStart(details);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (_controller.isAnimating) {
|
if (_controller.isAnimating) {
|
||||||
_controller
|
_controller
|
||||||
@@ -300,6 +309,11 @@ class _MouseInteractiveViewerState extends State<MouseInteractiveViewer>
|
|||||||
// Handle an update to an ongoing gesture. All of pan, scale, and rotate are
|
// Handle an update to an ongoing gesture. All of pan, scale, and rotate are
|
||||||
// handled with GestureDetector's scale gesture.
|
// handled with GestureDetector's scale gesture.
|
||||||
void _onScaleUpdate(ScaleUpdateDetails details) {
|
void _onScaleUpdate(ScaleUpdateDetails details) {
|
||||||
|
if (_isSinglePointer) {
|
||||||
|
widget.onPanUpdate(details);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
final double scale = _transformer.value.getMaxScaleOnAxis();
|
final double scale = _transformer.value.getMaxScaleOnAxis();
|
||||||
_scaleAnimationFocalPoint = details.localFocalPoint;
|
_scaleAnimationFocalPoint = details.localFocalPoint;
|
||||||
final Offset focalPointScene = _transformer.toScene(
|
final Offset focalPointScene = _transformer.toScene(
|
||||||
@@ -316,7 +330,6 @@ class _MouseInteractiveViewerState extends State<MouseInteractiveViewer>
|
|||||||
_gestureType ??= _getGestureType(details);
|
_gestureType ??= _getGestureType(details);
|
||||||
}
|
}
|
||||||
if (!_gestureIsSupported(_gestureType)) {
|
if (!_gestureIsSupported(_gestureType)) {
|
||||||
widget.onInteractionUpdate?.call(details);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -356,7 +369,6 @@ class _MouseInteractiveViewerState extends State<MouseInteractiveViewer>
|
|||||||
|
|
||||||
case _GestureType.rotate:
|
case _GestureType.rotate:
|
||||||
if (details.rotation == 0.0) {
|
if (details.rotation == 0.0) {
|
||||||
widget.onInteractionUpdate?.call(details);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final double desiredRotation = _rotationStart! + details.rotation;
|
final double desiredRotation = _rotationStart! + details.rotation;
|
||||||
@@ -373,7 +385,6 @@ class _MouseInteractiveViewerState extends State<MouseInteractiveViewer>
|
|||||||
// In an effort to keep the behavior similar whether or not scaleEnabled
|
// In an effort to keep the behavior similar whether or not scaleEnabled
|
||||||
// is true, these gestures are thrown away.
|
// is true, these gestures are thrown away.
|
||||||
if (details.scale != 1.0) {
|
if (details.scale != 1.0) {
|
||||||
widget.onInteractionUpdate?.call(details);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_currentAxis ??= _getPanAxis(_referenceFocalPoint!, focalPointScene);
|
_currentAxis ??= _getPanAxis(_referenceFocalPoint!, focalPointScene);
|
||||||
@@ -387,13 +398,16 @@ class _MouseInteractiveViewerState extends State<MouseInteractiveViewer>
|
|||||||
);
|
);
|
||||||
_referenceFocalPoint = _transformer.toScene(details.localFocalPoint);
|
_referenceFocalPoint = _transformer.toScene(details.localFocalPoint);
|
||||||
}
|
}
|
||||||
widget.onInteractionUpdate?.call(details);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle the end of a gesture of _GestureType. All of pan, scale, and rotate
|
// Handle the end of a gesture of _GestureType. All of pan, scale, and rotate
|
||||||
// are handled with GestureDetector's scale gesture.
|
// are handled with GestureDetector's scale gesture.
|
||||||
void _onScaleEnd(ScaleEndDetails details) {
|
void _onScaleEnd(ScaleEndDetails details) {
|
||||||
widget.onInteractionEnd?.call(details);
|
if (_isSinglePointer) {
|
||||||
|
widget.onPanEnd(details);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
_scaleStart = null;
|
_scaleStart = null;
|
||||||
_rotationStart = null;
|
_rotationStart = null;
|
||||||
_referenceFocalPoint = null;
|
_referenceFocalPoint = null;
|
||||||
@@ -481,10 +495,6 @@ class _MouseInteractiveViewerState extends State<MouseInteractiveViewer>
|
|||||||
final double scaleChange;
|
final double scaleChange;
|
||||||
if (event is PointerScrollEvent) {
|
if (event is PointerScrollEvent) {
|
||||||
if (event.kind == PointerDeviceKind.trackpad) {
|
if (event.kind == PointerDeviceKind.trackpad) {
|
||||||
widget.onInteractionStart?.call(
|
|
||||||
ScaleStartDetails(focalPoint: global, localFocalPoint: local),
|
|
||||||
);
|
|
||||||
|
|
||||||
final Offset localDelta = PointerEvent.transformDeltaViaPositions(
|
final Offset localDelta = PointerEvent.transformDeltaViaPositions(
|
||||||
untransformedEndPosition: global + event.scrollDelta,
|
untransformedEndPosition: global + event.scrollDelta,
|
||||||
untransformedDelta: event.scrollDelta,
|
untransformedDelta: event.scrollDelta,
|
||||||
@@ -501,14 +511,6 @@ class _MouseInteractiveViewerState extends State<MouseInteractiveViewer>
|
|||||||
newFocalPointScene - focalPointScene,
|
newFocalPointScene - focalPointScene,
|
||||||
);
|
);
|
||||||
|
|
||||||
widget.onInteractionUpdate?.call(
|
|
||||||
ScaleUpdateDetails(
|
|
||||||
focalPoint: global - event.scrollDelta,
|
|
||||||
localFocalPoint: local - localDelta,
|
|
||||||
focalPointDelta: -localDelta,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
widget.onInteractionEnd?.call(ScaleEndDetails());
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_handlePointerScrollEvent(event);
|
_handlePointerScrollEvent(event);
|
||||||
@@ -518,19 +520,8 @@ class _MouseInteractiveViewerState extends State<MouseInteractiveViewer>
|
|||||||
} else {
|
} else {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
widget.onInteractionStart?.call(
|
|
||||||
ScaleStartDetails(focalPoint: global, localFocalPoint: local),
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!_gestureIsSupported(_GestureType.scale)) {
|
if (!_gestureIsSupported(_GestureType.scale)) {
|
||||||
widget.onInteractionUpdate?.call(
|
|
||||||
ScaleUpdateDetails(
|
|
||||||
focalPoint: global,
|
|
||||||
localFocalPoint: local,
|
|
||||||
scale: scaleChange,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
widget.onInteractionEnd?.call(ScaleEndDetails());
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -544,22 +535,12 @@ class _MouseInteractiveViewerState extends State<MouseInteractiveViewer>
|
|||||||
_transformer.value,
|
_transformer.value,
|
||||||
focalPointSceneScaled - focalPointScene,
|
focalPointSceneScaled - focalPointScene,
|
||||||
);
|
);
|
||||||
|
|
||||||
widget.onInteractionUpdate?.call(
|
|
||||||
ScaleUpdateDetails(
|
|
||||||
focalPoint: global,
|
|
||||||
localFocalPoint: local,
|
|
||||||
scale: scaleChange,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
widget.onInteractionEnd?.call(ScaleEndDetails());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _handlePointerScrollEvent(PointerScrollEvent event) {
|
void _handlePointerScrollEvent(PointerScrollEvent event) {
|
||||||
final Offset local = event.localPosition;
|
|
||||||
final Offset global = event.position;
|
|
||||||
|
|
||||||
if (_gestureIsSupported(_GestureType.scale)) {
|
if (_gestureIsSupported(_GestureType.scale)) {
|
||||||
|
final Offset local = event.localPosition;
|
||||||
|
final Offset global = event.position;
|
||||||
if (HardwareKeyboard.instance.isControlPressed) {
|
if (HardwareKeyboard.instance.isControlPressed) {
|
||||||
_handleMouseWheelScale(event, local, global);
|
_handleMouseWheelScale(event, local, global);
|
||||||
return;
|
return;
|
||||||
@@ -569,16 +550,8 @@ class _MouseInteractiveViewerState extends State<MouseInteractiveViewer>
|
|||||||
_handleMouseWheelPanAsScale(event, local, global, shift);
|
_handleMouseWheelPanAsScale(event, local, global, shift);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
widget.pointerSignalFallback?.call(event);
|
widget.pointerSignalFallback(event);
|
||||||
}
|
}
|
||||||
widget.onInteractionUpdate?.call(
|
|
||||||
ScaleUpdateDetails(
|
|
||||||
focalPoint: global,
|
|
||||||
localFocalPoint: local,
|
|
||||||
scale: math.exp(-event.scrollDelta.dy / widget.scaleFactor),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
widget.onInteractionEnd?.call(ScaleEndDetails());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _handleMouseWheelScale(
|
void _handleMouseWheelScale(
|
||||||
@@ -597,15 +570,6 @@ class _MouseInteractiveViewerState extends State<MouseInteractiveViewer>
|
|||||||
_transformer.value,
|
_transformer.value,
|
||||||
focalPointSceneScaled - focalPointScene,
|
focalPointSceneScaled - focalPointScene,
|
||||||
);
|
);
|
||||||
|
|
||||||
widget.onInteractionUpdate?.call(
|
|
||||||
ScaleUpdateDetails(
|
|
||||||
focalPoint: global,
|
|
||||||
localFocalPoint: local,
|
|
||||||
scale: scaleChange,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
widget.onInteractionEnd?.call(ScaleEndDetails());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _handleMouseWheelPanAsScale(
|
void _handleMouseWheelPanAsScale(
|
||||||
@@ -625,8 +589,6 @@ class _MouseInteractiveViewerState extends State<MouseInteractiveViewer>
|
|||||||
_transformer.value,
|
_transformer.value,
|
||||||
newFocalPointScene - focalPointScene,
|
newFocalPointScene - focalPointScene,
|
||||||
);
|
);
|
||||||
|
|
||||||
widget.onTranslate();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _handleInertiaAnimation() {
|
void _handleInertiaAnimation() {
|
||||||
@@ -675,33 +637,18 @@ class _MouseInteractiveViewerState extends State<MouseInteractiveViewer>
|
|||||||
setState(() {});
|
setState(() {});
|
||||||
}
|
}
|
||||||
|
|
||||||
void _onPointerDown(PointerDownEvent event) {
|
|
||||||
final localPosition = event.localPosition;
|
|
||||||
if (localPosition.dx < 40 || localPosition.dy < 40) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
widget.onPointerDown?.call(event);
|
|
||||||
_scaleGestureRecognizer.addPointer(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
_scaleGestureRecognizer =
|
_scaleGestureRecognizer = widget.scaleGestureRecognizer
|
||||||
ScaleGestureRecognizer(
|
..gestureSettings = gestureSettings
|
||||||
debugOwner: this,
|
..onStart = _onScaleStart
|
||||||
dragStartBehavior: .start,
|
..onUpdate = _onScaleUpdate
|
||||||
allowedButtonsFilter: (buttons) => buttons == kPrimaryButton,
|
..onEnd = _onScaleEnd;
|
||||||
trackpadScrollToScaleFactor: Offset(0, -1 / widget.scaleFactor),
|
|
||||||
trackpadScrollCausesScale: widget.trackpadScrollCausesScale,
|
|
||||||
)
|
|
||||||
..gestureSettings = gestureSettings
|
|
||||||
..onStart = _onScaleStart
|
|
||||||
..onUpdate = _onScaleUpdate
|
|
||||||
..onEnd = _onScaleEnd;
|
|
||||||
_controller = AnimationController(vsync: this);
|
_controller = AnimationController(vsync: this);
|
||||||
_scaleController = AnimationController(vsync: this);
|
_scaleController = AnimationController(vsync: this);
|
||||||
|
|
||||||
|
_transformer = widget.transformationController;
|
||||||
_transformer.addListener(_handleTransformation);
|
_transformer.addListener(_handleTransformation);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -709,28 +656,20 @@ class _MouseInteractiveViewerState extends State<MouseInteractiveViewer>
|
|||||||
void didUpdateWidget(MouseInteractiveViewer oldWidget) {
|
void didUpdateWidget(MouseInteractiveViewer oldWidget) {
|
||||||
super.didUpdateWidget(oldWidget);
|
super.didUpdateWidget(oldWidget);
|
||||||
|
|
||||||
final TransformationController? newController =
|
final newController = widget.transformationController;
|
||||||
widget.transformationController;
|
|
||||||
if (newController == oldWidget.transformationController) {
|
if (newController == oldWidget.transformationController) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_transformer.removeListener(_handleTransformation);
|
_transformer.removeListener(_handleTransformation);
|
||||||
if (oldWidget.transformationController == null) {
|
_transformer = newController;
|
||||||
_transformer.dispose();
|
|
||||||
}
|
|
||||||
_transformer = newController ?? TransformationController();
|
|
||||||
_transformer.addListener(_handleTransformation);
|
_transformer.addListener(_handleTransformation);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
_scaleGestureRecognizer.dispose();
|
|
||||||
_controller.dispose();
|
_controller.dispose();
|
||||||
_scaleController.dispose();
|
_scaleController.dispose();
|
||||||
_transformer.removeListener(_handleTransformation);
|
_transformer.removeListener(_handleTransformation);
|
||||||
if (widget.transformationController == null) {
|
|
||||||
_transformer.dispose();
|
|
||||||
}
|
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -742,7 +681,7 @@ class _MouseInteractiveViewerState extends State<MouseInteractiveViewer>
|
|||||||
key: _parentKey,
|
key: _parentKey,
|
||||||
behavior: HitTestBehavior.opaque,
|
behavior: HitTestBehavior.opaque,
|
||||||
onPointerSignal: _receivedPointerSignal,
|
onPointerSignal: _receivedPointerSignal,
|
||||||
onPointerDown: _onPointerDown,
|
onPointerDown: widget.onPointerDown,
|
||||||
onPointerPanZoomStart: _scaleGestureRecognizer.addPointerPanZoom,
|
onPointerPanZoomStart: _scaleGestureRecognizer.addPointerPanZoom,
|
||||||
onPointerPanZoomUpdate: widget.onPointerPanZoomUpdate,
|
onPointerPanZoomUpdate: widget.onPointerPanZoomUpdate,
|
||||||
onPointerPanZoomEnd: widget.onPointerPanZoomEnd,
|
onPointerPanZoomEnd: widget.onPointerPanZoomEnd,
|
||||||
|
|||||||
@@ -110,7 +110,7 @@ class PLVideoPlayer extends StatefulWidget {
|
|||||||
|
|
||||||
class _PLVideoPlayerState extends State<PLVideoPlayer>
|
class _PLVideoPlayerState extends State<PLVideoPlayer>
|
||||||
with WidgetsBindingObserver, TickerProviderStateMixin {
|
with WidgetsBindingObserver, TickerProviderStateMixin {
|
||||||
late AnimationController animationController;
|
late AnimationController _animationController;
|
||||||
late VideoController videoController;
|
late VideoController videoController;
|
||||||
late final CommonIntroController introController = widget.introController!;
|
late final CommonIntroController introController = widget.introController!;
|
||||||
late final VideoDetailController videoDetailController =
|
late final VideoDetailController videoDetailController =
|
||||||
@@ -126,15 +126,7 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
|
|||||||
late final RxBool showRestoreScaleBtn = false.obs;
|
late final RxBool showRestoreScaleBtn = false.obs;
|
||||||
|
|
||||||
GestureType? _gestureType;
|
GestureType? _gestureType;
|
||||||
|
Offset? _initialFocalPoint;
|
||||||
Offset initialFocalPoint = Offset.zero;
|
|
||||||
|
|
||||||
//播放器放缩
|
|
||||||
bool interacting = false;
|
|
||||||
|
|
||||||
// 阅读器限制
|
|
||||||
// Timer? _accessibilityDebounce;
|
|
||||||
// double _lastAnnouncedValue = -1;
|
|
||||||
|
|
||||||
bool _pauseDueToPauseUponEnteringBackgroundMode = false;
|
bool _pauseDueToPauseUponEnteringBackgroundMode = false;
|
||||||
|
|
||||||
@@ -161,9 +153,9 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (visible) {
|
if (visible) {
|
||||||
animationController.forward();
|
_animationController.forward();
|
||||||
} else {
|
} else {
|
||||||
animationController.reverse();
|
_animationController.reverse();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (widget.videoDetailController case final controller?) {
|
if (widget.videoDetailController case final controller?) {
|
||||||
@@ -197,9 +189,9 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
|
|||||||
_onControlChanged,
|
_onControlChanged,
|
||||||
);
|
);
|
||||||
|
|
||||||
transformationController = TransformationController();
|
_transformationController = TransformationController();
|
||||||
|
|
||||||
animationController = AnimationController(
|
_animationController = AnimationController(
|
||||||
vsync: this,
|
vsync: this,
|
||||||
duration: const Duration(milliseconds: 100),
|
duration: const Duration(milliseconds: 100),
|
||||||
);
|
);
|
||||||
@@ -250,6 +242,17 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
|
|||||||
_tapGestureRecognizer = TapGestureRecognizer()..onTapUp = _onTapUp;
|
_tapGestureRecognizer = TapGestureRecognizer()..onTapUp = _onTapUp;
|
||||||
_doubleTapGestureRecognizer = DoubleTapGestureRecognizer()
|
_doubleTapGestureRecognizer = DoubleTapGestureRecognizer()
|
||||||
..onDoubleTapDown = _onDoubleTapDown;
|
..onDoubleTapDown = _onDoubleTapDown;
|
||||||
|
|
||||||
|
_scaleGestureRecognizer = ScaleGestureRecognizer(
|
||||||
|
debugOwner: this,
|
||||||
|
dragStartBehavior: .start,
|
||||||
|
allowedButtonsFilter: (buttons) => buttons == kPrimaryButton,
|
||||||
|
trackpadScrollToScaleFactor: const Offset(
|
||||||
|
0,
|
||||||
|
-1 / kDefaultMouseScrollToScaleFactor,
|
||||||
|
),
|
||||||
|
trackpadScrollCausesScale: false,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -289,17 +292,17 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
|
|||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
removeObserverMobile(this);
|
removeObserverMobile(this);
|
||||||
_danmakuListener?.cancel();
|
|
||||||
_tapGestureRecognizer.dispose();
|
_tapGestureRecognizer.dispose();
|
||||||
_longPressRecognizer?.dispose();
|
_longPressRecognizer?.dispose();
|
||||||
_doubleTapGestureRecognizer.dispose();
|
_doubleTapGestureRecognizer.dispose();
|
||||||
|
_scaleGestureRecognizer.dispose();
|
||||||
_brightnessListener?.cancel();
|
_brightnessListener?.cancel();
|
||||||
_controlsListener?.cancel();
|
_controlsListener?.cancel();
|
||||||
animationController.dispose();
|
_animationController.dispose();
|
||||||
|
_transformationController.dispose();
|
||||||
if (PlatformUtils.isMobile) {
|
if (PlatformUtils.isMobile) {
|
||||||
FlutterVolumeController.removeListener();
|
FlutterVolumeController.removeListener();
|
||||||
}
|
}
|
||||||
transformationController.dispose();
|
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -800,7 +803,7 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
|
|||||||
|
|
||||||
bool get isFullScreen => plPlayerController.isFullScreen.value;
|
bool get isFullScreen => plPlayerController.isFullScreen.value;
|
||||||
|
|
||||||
late final TransformationController transformationController;
|
late final TransformationController _transformationController;
|
||||||
|
|
||||||
late ColorScheme colorScheme;
|
late ColorScheme colorScheme;
|
||||||
late double maxWidth;
|
late double maxWidth;
|
||||||
@@ -812,74 +815,55 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
|
|||||||
colorScheme = ColorScheme.of(context);
|
colorScheme = ColorScheme.of(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _onInteractionStart(ScaleStartDetails details) {
|
void _onPanStart(ScaleStartDetails details) {
|
||||||
if (plPlayerController.controlsLock.value) return;
|
|
||||||
final localFocalPoint = details.localFocalPoint;
|
|
||||||
if (localFocalPoint.dx > maxWidth - 40 ||
|
|
||||||
localFocalPoint.dy > maxHeight - 40) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (details.pointerCount > 1) {
|
|
||||||
interacting = true;
|
|
||||||
}
|
|
||||||
initialFocalPoint = localFocalPoint;
|
|
||||||
_gestureType = null;
|
_gestureType = null;
|
||||||
|
_initialFocalPoint = details.localFocalPoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _onInteractionUpdate(ScaleUpdateDetails details) {
|
void _onScaleUpdate(double scale) {
|
||||||
showRestoreScaleBtn.value =
|
showRestoreScaleBtn.value = scale != 1.0;
|
||||||
transformationController.value.storage[0] != 1.0;
|
}
|
||||||
if (interacting || initialFocalPoint == Offset.zero) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Offset cumulativeDelta = details.localFocalPoint - initialFocalPoint;
|
|
||||||
if (details.pointerCount > 1 && cumulativeDelta.distanceSquared < 2.25) {
|
|
||||||
interacting = true;
|
|
||||||
_gestureType = null;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 锁定时禁用
|
|
||||||
if (plPlayerController.controlsLock.value) return;
|
|
||||||
|
|
||||||
|
void _onPanUpdate(ScaleUpdateDetails details) {
|
||||||
if (_gestureType == null) {
|
if (_gestureType == null) {
|
||||||
|
final cumulativeDelta = details.localFocalPoint - _initialFocalPoint!;
|
||||||
if (cumulativeDelta.distanceSquared < 1) return;
|
if (cumulativeDelta.distanceSquared < 1) return;
|
||||||
final dx = cumulativeDelta.dx.abs();
|
final dx = cumulativeDelta.dx.abs();
|
||||||
final dy = cumulativeDelta.dy.abs();
|
final dy = cumulativeDelta.dy.abs();
|
||||||
if (dx > 3 * dy) {
|
|
||||||
_gestureType = GestureType.horizontal;
|
|
||||||
} else if (dy > 3 * dx) {
|
|
||||||
// _gestureType = 'vertical';
|
|
||||||
|
|
||||||
|
if (dx > 3 * dy) {
|
||||||
|
_gestureType = .horizontal;
|
||||||
|
} else if (dy > 3 * dx) {
|
||||||
final double tapPosition = details.localFocalPoint.dx;
|
final double tapPosition = details.localFocalPoint.dx;
|
||||||
final double sectionWidth = maxWidth / 3;
|
final double sectionWidth = maxWidth / 3;
|
||||||
if (tapPosition < sectionWidth) {
|
if (tapPosition < sectionWidth) {
|
||||||
if (PlatformUtils.isDesktop) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// 左边区域
|
// 左边区域
|
||||||
_gestureType = GestureType.left;
|
if (PlatformUtils.isDesktop) {
|
||||||
|
_gestureType = .right;
|
||||||
|
} else {
|
||||||
|
_gestureType = .left;
|
||||||
|
}
|
||||||
} else if (tapPosition < sectionWidth * 2) {
|
} else if (tapPosition < sectionWidth * 2) {
|
||||||
// 全屏
|
// 全屏
|
||||||
_gestureType = GestureType.center;
|
_gestureType = .center;
|
||||||
} else {
|
} else {
|
||||||
// 右边区域
|
// 右边区域
|
||||||
_gestureType = GestureType.right;
|
_gestureType = .right;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Offset delta = details.focalPointDelta;
|
final delta = details.focalPointDelta;
|
||||||
|
|
||||||
if (_gestureType == GestureType.horizontal) {
|
if (_gestureType == .horizontal) {
|
||||||
// live模式下禁用
|
// live模式下禁用
|
||||||
if (plPlayerController.isLive) return;
|
if (plPlayerController.isLive) return;
|
||||||
|
|
||||||
final int curSliderPosition =
|
final curSliderPosition =
|
||||||
plPlayerController.sliderPosition.inMilliseconds;
|
plPlayerController.sliderPosition.inMilliseconds;
|
||||||
final int newPos =
|
final newPos =
|
||||||
(curSliderPosition +
|
(curSliderPosition +
|
||||||
(plPlayerController.sliderScale * delta.dx / maxWidth)
|
(plPlayerController.sliderScale * delta.dx / maxWidth)
|
||||||
.round())
|
.round())
|
||||||
@@ -934,31 +918,25 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
|
|||||||
plPlayerController.cancelSeek != true) {
|
plPlayerController.cancelSeek != true) {
|
||||||
plPlayerController.updatePreviewIndex(newPos ~/ 1000);
|
plPlayerController.updatePreviewIndex(newPos ~/ 1000);
|
||||||
}
|
}
|
||||||
} else if (_gestureType == GestureType.left) {
|
} else if (_gestureType == .left) {
|
||||||
// 左边区域 👈
|
// 左边区域 👈
|
||||||
final double level = maxHeight * 3;
|
final double level = maxHeight * 3;
|
||||||
final double brightness = (_brightnessValue.value - delta.dy / level)
|
final double brightness = (_brightnessValue.value - delta.dy / level)
|
||||||
.clamp(0.0, 1.0);
|
.clamp(0.0, 1.0);
|
||||||
setBrightness(brightness);
|
setBrightness(brightness);
|
||||||
} else if (_gestureType == GestureType.center) {
|
} else if (_gestureType == .center) {
|
||||||
// 全屏
|
// 全屏
|
||||||
const double threshold = 2.5; // 滑动阈值
|
const double threshold = 2.5; // 滑动阈值
|
||||||
double cumulativeDy = details.localFocalPoint.dy - initialFocalPoint.dy;
|
double cumulativeDy = details.localFocalPoint.dy - _initialFocalPoint!.dy;
|
||||||
|
|
||||||
if (cumulativeDy > threshold) {
|
if (cumulativeDy > threshold) {
|
||||||
_gestureType = GestureType.center_down;
|
_gestureType = .center_down;
|
||||||
if (isFullScreen) {
|
plPlayerController.triggerFullScreen(status: false);
|
||||||
plPlayerController.triggerFullScreen(status: false);
|
|
||||||
}
|
|
||||||
// if (kDebugMode) debugPrint('center_down:$cumulativeDy');
|
|
||||||
} else if (cumulativeDy < -threshold) {
|
} else if (cumulativeDy < -threshold) {
|
||||||
_gestureType = GestureType.center_up;
|
_gestureType = .center_up;
|
||||||
if (!isFullScreen) {
|
plPlayerController.triggerFullScreen(status: true);
|
||||||
plPlayerController.triggerFullScreen(status: true);
|
|
||||||
}
|
|
||||||
// if (kDebugMode) debugPrint('center_up:$cumulativeDy');
|
|
||||||
}
|
}
|
||||||
} else if (_gestureType == GestureType.right) {
|
} else if (_gestureType == .right) {
|
||||||
// 右边区域
|
// 右边区域
|
||||||
final double level = maxHeight * 0.5;
|
final double level = maxHeight * 0.5;
|
||||||
EasyThrottle.throttle(
|
EasyThrottle.throttle(
|
||||||
@@ -976,7 +954,7 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _onInteractionEnd(ScaleEndDetails details) {
|
void _onPanEnd(ScaleEndDetails details) {
|
||||||
if (Platform.isAndroid && _gestureType == .left) {
|
if (Platform.isAndroid && _gestureType == .left) {
|
||||||
ScreenBrightnessPlatform.instance.restoreBrightnessMode();
|
ScreenBrightnessPlatform.instance.restoreBrightnessMode();
|
||||||
}
|
}
|
||||||
@@ -994,15 +972,11 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
|
|||||||
}
|
}
|
||||||
plPlayerController.onChangedSliderEnd();
|
plPlayerController.onChangedSliderEnd();
|
||||||
}
|
}
|
||||||
interacting = false;
|
_initialFocalPoint = null;
|
||||||
initialFocalPoint = Offset.zero;
|
|
||||||
_gestureType = null;
|
_gestureType = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
void onDoubleTapDownMobile(TapDownDetails details) {
|
void onDoubleTapDownMobile(TapDownDetails details) {
|
||||||
if (plPlayerController.isLive || plPlayerController.controlsLock.value) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
final double tapPosition = details.localPosition.dx;
|
final double tapPosition = details.localPosition.dx;
|
||||||
final double sectionWidth = maxWidth / 4;
|
final double sectionWidth = maxWidth / 4;
|
||||||
DoubleTapType type;
|
DoubleTapType type;
|
||||||
@@ -1016,39 +990,21 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
|
|||||||
plPlayerController.doubleTapFuc(type);
|
plPlayerController.doubleTapFuc(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
void onTapDesktop() {
|
|
||||||
if (plPlayerController.isLive || plPlayerController.controlsLock.value) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
plPlayerController.onDoubleTapCenter();
|
|
||||||
}
|
|
||||||
|
|
||||||
void onDoubleTapDesktop() {
|
|
||||||
if (plPlayerController.controlsLock.value) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
plPlayerController.triggerFullScreen(status: !isFullScreen);
|
|
||||||
}
|
|
||||||
|
|
||||||
void _onTapUp(TapUpDetails details) {
|
void _onTapUp(TapUpDetails details) {
|
||||||
switch (details.kind) {
|
switch (details.kind) {
|
||||||
case ui.PointerDeviceKind.mouse when PlatformUtils.isDesktop:
|
case ui.PointerDeviceKind.mouse when PlatformUtils.isDesktop:
|
||||||
onTapDesktop();
|
plPlayerController.onDoubleTapCenter();
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
plPlayerController.controls = !plPlayerController.showControls.value;
|
plPlayerController.controls = !plPlayerController.showControls.value;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _onDoubleTapDown(TapDownDetails details) {
|
void _onDoubleTapDown(TapDownDetails details) {
|
||||||
switch (details.kind) {
|
switch (details.kind) {
|
||||||
case ui.PointerDeviceKind.mouse when PlatformUtils.isDesktop:
|
case ui.PointerDeviceKind.mouse when PlatformUtils.isDesktop:
|
||||||
onDoubleTapDesktop();
|
plPlayerController.triggerFullScreen(status: !isFullScreen);
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
onDoubleTapDownMobile(details);
|
onDoubleTapDownMobile(details);
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1062,7 +1018,18 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
|
|||||||
plPlayerController.setLongPressStatus(false));
|
plPlayerController.setLongPressStatus(false));
|
||||||
late final TapGestureRecognizer _tapGestureRecognizer;
|
late final TapGestureRecognizer _tapGestureRecognizer;
|
||||||
late final DoubleTapGestureRecognizer _doubleTapGestureRecognizer;
|
late final DoubleTapGestureRecognizer _doubleTapGestureRecognizer;
|
||||||
StreamSubscription<bool>? _danmakuListener;
|
late final ScaleGestureRecognizer _scaleGestureRecognizer;
|
||||||
|
|
||||||
|
static const _kOffsetThreshold = 40.0;
|
||||||
|
bool _isPositionAllowed(Offset offset) {
|
||||||
|
if (offset.dx < _kOffsetThreshold ||
|
||||||
|
offset.dy < _kOffsetThreshold ||
|
||||||
|
offset.dx > maxWidth - _kOffsetThreshold ||
|
||||||
|
offset.dy > maxHeight - _kOffsetThreshold) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void _onPointerDown(PointerDownEvent event) {
|
void _onPointerDown(PointerDownEvent event) {
|
||||||
if (PlatformUtils.isDesktop) {
|
if (PlatformUtils.isDesktop) {
|
||||||
@@ -1075,20 +1042,37 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
|
|||||||
..controlsLock.value = false
|
..controlsLock.value = false
|
||||||
..showControls.value = false;
|
..showControls.value = false;
|
||||||
}
|
}
|
||||||
plPlayerController
|
plPlayerController.triggerFullScreen(
|
||||||
.triggerFullScreen(
|
status: !isFullScreen,
|
||||||
status: !isFullScreen,
|
inAppFullScreen: isSecondaryBtn,
|
||||||
inAppFullScreen: isSecondaryBtn,
|
);
|
||||||
)
|
|
||||||
.whenComplete(() => initialFocalPoint = Offset.zero);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_tapGestureRecognizer.addPointer(event);
|
if (_isPositionAllowed(event.localPosition)) {
|
||||||
_doubleTapGestureRecognizer.addPointer(event);
|
final controlsUnlock = !plPlayerController.controlsLock.value;
|
||||||
if (!plPlayerController.isLive) {
|
if (PlatformUtils.isMobile) {
|
||||||
longPressRecognizer.addPointer(event);
|
_tapGestureRecognizer.addPointer(event);
|
||||||
|
if (controlsUnlock) {
|
||||||
|
if (!plPlayerController.isLive) {
|
||||||
|
_doubleTapGestureRecognizer.addPointer(event);
|
||||||
|
longPressRecognizer.addPointer(event);
|
||||||
|
}
|
||||||
|
_scaleGestureRecognizer.addPointer(event);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (controlsUnlock) {
|
||||||
|
if (plPlayerController.isLive) {
|
||||||
|
_doubleTapGestureRecognizer.addPointer(event);
|
||||||
|
} else {
|
||||||
|
_tapGestureRecognizer.addPointer(event);
|
||||||
|
_doubleTapGestureRecognizer.addPointer(event);
|
||||||
|
longPressRecognizer.addPointer(event);
|
||||||
|
}
|
||||||
|
_scaleGestureRecognizer.addPointer(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1100,14 +1084,14 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
|
|||||||
final dx = pan.dx.abs();
|
final dx = pan.dx.abs();
|
||||||
final dy = pan.dy.abs();
|
final dy = pan.dy.abs();
|
||||||
if (dx > 3 * dy) {
|
if (dx > 3 * dy) {
|
||||||
_gestureType = GestureType.horizontal;
|
_gestureType = .horizontal;
|
||||||
} else if (dy > 3 * dx) {
|
} else if (dy > 3 * dx) {
|
||||||
_gestureType = GestureType.right;
|
_gestureType = .right;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_gestureType == GestureType.horizontal) {
|
if (_gestureType == .horizontal) {
|
||||||
if (plPlayerController.isLive) return;
|
if (plPlayerController.isLive) return;
|
||||||
|
|
||||||
Offset delta = event.localPanDelta;
|
Offset delta = event.localPanDelta;
|
||||||
@@ -1131,7 +1115,7 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
|
|||||||
plPlayerController.cancelSeek != true) {
|
plPlayerController.cancelSeek != true) {
|
||||||
plPlayerController.updatePreviewIndex(newPos ~/ 1000);
|
plPlayerController.updatePreviewIndex(newPos ~/ 1000);
|
||||||
}
|
}
|
||||||
} else if (_gestureType == GestureType.right) {
|
} else if (_gestureType == .right) {
|
||||||
final double level = maxHeight * 0.5;
|
final double level = maxHeight * 0.5;
|
||||||
EasyThrottle.throttle(
|
EasyThrottle.throttle(
|
||||||
'setVolume',
|
'setVolume',
|
||||||
@@ -1149,6 +1133,12 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
|
|||||||
}
|
}
|
||||||
|
|
||||||
void _onPointerPanZoomEnd(PointerPanZoomEndEvent event) {
|
void _onPointerPanZoomEnd(PointerPanZoomEndEvent event) {
|
||||||
|
plPlayerController.showPreview.value = false;
|
||||||
|
if (plPlayerController.isSliderMoving.value) {
|
||||||
|
plPlayerController
|
||||||
|
..seekTo(plPlayerController.sliderPosition, isSeek: false)
|
||||||
|
..onChangedSliderEnd();
|
||||||
|
}
|
||||||
_gestureType = null;
|
_gestureType = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1413,7 +1403,7 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
|
|||||||
children: [
|
children: [
|
||||||
AppBarAni(
|
AppBarAni(
|
||||||
isTop: true,
|
isTop: true,
|
||||||
controller: animationController,
|
controller: _animationController,
|
||||||
isFullScreen: isFullScreen,
|
isFullScreen: isFullScreen,
|
||||||
child: plPlayerController.isDesktopPip
|
child: plPlayerController.isDesktopPip
|
||||||
? GestureDetector(
|
? GestureDetector(
|
||||||
@@ -1425,7 +1415,7 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
|
|||||||
),
|
),
|
||||||
AppBarAni(
|
AppBarAni(
|
||||||
isTop: false,
|
isTop: false,
|
||||||
controller: animationController,
|
controller: _animationController,
|
||||||
isFullScreen: isFullScreen,
|
isFullScreen: isFullScreen,
|
||||||
child:
|
child:
|
||||||
widget.bottomControl ??
|
widget.bottomControl ??
|
||||||
@@ -1489,12 +1479,12 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
|
|||||||
);
|
);
|
||||||
final anim = animController.drive(
|
final anim = animController.drive(
|
||||||
Matrix4Tween(
|
Matrix4Tween(
|
||||||
begin: transformationController.value,
|
begin: _transformationController.value,
|
||||||
end: Matrix4.identity(),
|
end: Matrix4.identity(),
|
||||||
).chain(CurveTween(curve: Curves.easeOut)),
|
).chain(CurveTween(curve: Curves.easeOut)),
|
||||||
);
|
);
|
||||||
void listener() {
|
void listener() {
|
||||||
transformationController.value = anim.value;
|
_transformationController.value = anim.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
animController.addListener(listener);
|
animController.addListener(listener);
|
||||||
@@ -1792,7 +1782,7 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
|
|||||||
|
|
||||||
Widget get _videoWidget {
|
Widget get _videoWidget {
|
||||||
return Container(
|
return Container(
|
||||||
clipBehavior: Clip.none,
|
clipBehavior: .none,
|
||||||
width: maxWidth,
|
width: maxWidth,
|
||||||
height: maxHeight,
|
height: maxHeight,
|
||||||
color: widget.fill,
|
color: widget.fill,
|
||||||
@@ -1803,21 +1793,16 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
|
|||||||
onPointerPanZoomUpdate: _onPointerPanZoomUpdate,
|
onPointerPanZoomUpdate: _onPointerPanZoomUpdate,
|
||||||
onPointerPanZoomEnd: _onPointerPanZoomEnd,
|
onPointerPanZoomEnd: _onPointerPanZoomEnd,
|
||||||
onPointerDown: _onPointerDown,
|
onPointerDown: _onPointerDown,
|
||||||
onInteractionStart: _onInteractionStart,
|
onPanStart: _onPanStart,
|
||||||
onInteractionUpdate: _onInteractionUpdate,
|
onPanUpdate: _onPanUpdate,
|
||||||
onInteractionEnd: _onInteractionEnd,
|
onPanEnd: _onPanEnd,
|
||||||
|
onScaleUpdate: _onScaleUpdate,
|
||||||
|
scaleGestureRecognizer: _scaleGestureRecognizer,
|
||||||
panEnabled: false,
|
panEnabled: false,
|
||||||
minScale: 1.0,
|
minScale: 1.0,
|
||||||
maxScale: 2.0,
|
maxScale: 2.0,
|
||||||
panAxis: PanAxis.aligned,
|
panAxis: .aligned,
|
||||||
transformationController: transformationController,
|
transformationController: _transformationController,
|
||||||
onTranslate: () {
|
|
||||||
final storage = transformationController.value.storage;
|
|
||||||
showRestoreScaleBtn.value =
|
|
||||||
storage[12].abs() > 2.0 ||
|
|
||||||
storage[13].abs() > 2.0 ||
|
|
||||||
storage[0] != 1.0;
|
|
||||||
},
|
|
||||||
childKey: _videoKey,
|
childKey: _videoKey,
|
||||||
child: RepaintBoundary(
|
child: RepaintBoundary(
|
||||||
key: _videoKey,
|
key: _videoKey,
|
||||||
|
|||||||
Reference in New Issue
Block a user