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
widget.onInteractionEnd?.call(ScaleEndDetails());
return;
}
final RenderBox childRenderBox = _childKey.currentContext!.findRenderObject()! as RenderBox;
final Size childSize = childRenderBox.size;
final double scaleChange = 1.0 - event.scrollDelta.dy / childSize.height;
if (scaleChange == 0.0) {
// Ignore left and right scroll.
if (event.scrollDelta.dy == 0.0) {
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(
event.localPosition,
);
......
......@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:math' as math;
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
......@@ -673,6 +675,37 @@ void main() {
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{
final TransformationController transformationController = TransformationController();
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