Unverified Commit a3971153 authored by RomanJos's avatar RomanJos Committed by GitHub

[Proposal] Make mouseWheel zoom in % instead of pixels value (#71266)

InteractiveViewer scale gesture feel improvement.
parent b11521ad
...@@ -930,12 +930,15 @@ class _InteractiveViewerState extends State<InteractiveViewer> with TickerProvid ...@@ -930,12 +930,15 @@ class _InteractiveViewerState extends State<InteractiveViewer> with TickerProvid
widget.onInteractionEnd?.call(ScaleEndDetails()); widget.onInteractionEnd?.call(ScaleEndDetails());
return; return;
} }
final RenderBox childRenderBox = _childKey.currentContext!.findRenderObject()! as RenderBox;
final Size childSize = childRenderBox.size; // Ignore left and right scroll.
final double scaleChange = 1.0 - event.scrollDelta.dy / childSize.height; if (event.scrollDelta.dy == 0.0) {
if (scaleChange == 0.0) {
return; return;
} }
// In the Flutter engine, the mousewheel scrollDelta is hardcoded to 20 per scroll, while a trackpad scroll can be any amount.
// The calculation for scaleChange here was arbitrarily chosen to feel natural for both trackpads and mousewheels on all platforms.
final double scaleChange = math.exp(-event.scrollDelta.dy / 200);
final Offset focalPointScene = _transformationController!.toScene( final Offset focalPointScene = _transformationController!.toScene(
event.localPosition, event.localPosition,
); );
......
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import 'dart:math' as math;
import 'package:flutter/gestures.dart'; import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
...@@ -673,6 +675,37 @@ void main() { ...@@ -673,6 +675,37 @@ void main() {
expect(scenePoint, const Offset(100, 100)); expect(scenePoint, const Offset(100, 100));
}); });
testWidgets('Scaling amount is equal forth and back with a mouse scroll', (WidgetTester tester) async {
final TransformationController transformationController = TransformationController();
await tester.pumpWidget(
MaterialApp(
home: Scaffold(
body: Center(
child: InteractiveViewer(
constrained: false,
maxScale: 100000,
minScale: 0.01,
transformationController: transformationController,
child: Container(width: 1000.0, height: 1000.0),
),
)),
),
);
final Offset center = tester.getCenter(find.byType(InteractiveViewer));
await scrollAt(center, tester, const Offset(0.0, -200.0));
await tester.pumpAndSettle();
expect(transformationController.value.getMaxScaleOnAxis(), math.exp(200 / 200));
await scrollAt(center, tester, const Offset(0.0, -200.0));
await tester.pumpAndSettle();
// math.exp round the number too short compared to the one in transformationController.
expect(transformationController.value.getMaxScaleOnAxis(), closeTo(math.exp(400 / 200), 0.000000000000001));
await scrollAt(center, tester, const Offset(0.0, 200.0));
await scrollAt(center, tester, const Offset(0.0, 200.0));
await tester.pumpAndSettle();
expect(transformationController.value.getMaxScaleOnAxis(), 1.0);
});
testWidgets('onInteraction can be used to get scene point', (WidgetTester tester) async{ testWidgets('onInteraction can be used to get scene point', (WidgetTester tester) async{
final TransformationController transformationController = TransformationController(); final TransformationController transformationController = TransformationController();
late Offset focalPoint; late Offset focalPoint;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment