[Proposal] Make mouseWheel zoom in % instead of pixels value (#71266)
InteractiveViewer scale gesture feel improvement.
This commit is contained in:
parent
b11521ada5
commit
a3971153f6
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user