add mouse scroll to zoom functionality
This commit is contained in:
@@ -208,8 +208,9 @@ class LazyCanvasController with ChangeNotifier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Increment or decrement the scale by an additive delta value.
|
/// Increment or decrement the scale by an additive delta value.
|
||||||
void updateScalebyDelta(double delta) {
|
void updateScalebyDelta(double delta, {Offset? focalPoint}) {
|
||||||
final focalPoint = Offset(canvasSize.width / 2, canvasSize.height / 2);
|
// added focalPoint param
|
||||||
|
focalPoint ??= Offset(canvasSize.width / 2, canvasSize.height / 2);
|
||||||
final newScale = _scale + delta;
|
final newScale = _scale + delta;
|
||||||
_gsTopLeftOffset = newGsTopLeftOnScaling(_gsTopLeftOffset, focalPoint, _scale, newScale);
|
_gsTopLeftOffset = newGsTopLeftOnScaling(_gsTopLeftOffset, focalPoint, _scale, newScale);
|
||||||
_scale = newScale;
|
_scale = newScale;
|
||||||
|
|||||||
+56
-40
@@ -1,5 +1,7 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/rendering.dart';
|
import 'package:flutter/rendering.dart';
|
||||||
|
import 'package:flutter/services.dart'; // added for LogicalKeyboardKey
|
||||||
|
import 'package:flutter/gestures.dart'; // added for PointerScrollEvent
|
||||||
import '../utils/offset_extensions.dart';
|
import '../utils/offset_extensions.dart';
|
||||||
|
|
||||||
import '../utils/styles.dart';
|
import '../utils/styles.dart';
|
||||||
@@ -33,46 +35,61 @@ class _LazyCanvasState extends State<LazyCanvas> with TickerProviderStateMixin<L
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
widget.controller.setBuildContext(context);
|
widget.controller.setBuildContext(context);
|
||||||
return GestureDetector(
|
return Listener(
|
||||||
behavior: HitTestBehavior.translucent,
|
behavior: HitTestBehavior.translucent, // ensure scroll signals are captured even on empty space
|
||||||
onScaleUpdate: widget.controller.onScaleUpdate,
|
onPointerSignal: (event) {
|
||||||
onScaleStart: widget.controller.onScaleStart,
|
if (event is PointerScrollEvent) {
|
||||||
child: ListenableBuilder(
|
final pressed = RawKeyboard.instance.keysPressed;
|
||||||
listenable: widget.controller,
|
if (pressed.contains(LogicalKeyboardKey.controlLeft) || pressed.contains(LogicalKeyboardKey.controlRight)) {
|
||||||
builder: (_, _) {
|
// Typical mouse wheel up gives negative dy on many platforms; invert if needed
|
||||||
final childrenWithPositions = widget.controller.widgetsWithScreenPositions();
|
final delta = (-event.scrollDelta.dy) * 0.0015; // sensitivity
|
||||||
final ssPositions = childrenWithPositions.map((e) => e.ssPosition).toList();
|
if (delta != 0) {
|
||||||
final childrenIds = childrenWithPositions.map((e) => e.id).toList();
|
widget.controller.updateScalebyDelta(delta, focalPoint: event.localPosition);
|
||||||
final children = childrenWithPositions.map((e) => e.child).toList();
|
}
|
||||||
final canvas = _CanvasRenderObject(
|
|
||||||
childrenIds: childrenIds,
|
|
||||||
canvasBackground: widget.controller.background,
|
|
||||||
ssPositions: ssPositions,
|
|
||||||
scale: widget.controller.scale,
|
|
||||||
gridSpaceOffset: widget.controller.offset,
|
|
||||||
onCanvasSizeChange: widget.controller.onCanvasSizeChange,
|
|
||||||
onChildSizeChange: widget.controller.onChildSizeChange,
|
|
||||||
children: children,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (widget.controller.debug) {
|
|
||||||
return Stack(
|
|
||||||
children: [
|
|
||||||
canvas,
|
|
||||||
Positioned(
|
|
||||||
top: 16,
|
|
||||||
left: 16,
|
|
||||||
child: Text(
|
|
||||||
'Offset: ${widget.controller.offset.coord()}\nScale: ${widget.controller.scale.toStringAsFixed(1)}',
|
|
||||||
style: monospaceStyle,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return canvas;
|
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
},
|
||||||
|
child: GestureDetector(
|
||||||
|
behavior: HitTestBehavior.translucent,
|
||||||
|
onScaleUpdate: widget.controller.onScaleUpdate,
|
||||||
|
onScaleStart: widget.controller.onScaleStart,
|
||||||
|
child: ListenableBuilder(
|
||||||
|
listenable: widget.controller,
|
||||||
|
builder: (_, _) {
|
||||||
|
final childrenWithPositions = widget.controller.widgetsWithScreenPositions();
|
||||||
|
final ssPositions = childrenWithPositions.map((e) => e.ssPosition).toList();
|
||||||
|
final childrenIds = childrenWithPositions.map((e) => e.id).toList();
|
||||||
|
final children = childrenWithPositions.map((e) => e.child).toList();
|
||||||
|
final canvas = _CanvasRenderObject(
|
||||||
|
childrenIds: childrenIds,
|
||||||
|
canvasBackground: widget.controller.background,
|
||||||
|
ssPositions: ssPositions,
|
||||||
|
scale: widget.controller.scale,
|
||||||
|
gridSpaceOffset: widget.controller.offset,
|
||||||
|
onCanvasSizeChange: widget.controller.onCanvasSizeChange,
|
||||||
|
onChildSizeChange: widget.controller.onChildSizeChange,
|
||||||
|
children: children,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (widget.controller.debug) {
|
||||||
|
return Stack(
|
||||||
|
children: [
|
||||||
|
canvas,
|
||||||
|
Positioned(
|
||||||
|
top: 16,
|
||||||
|
left: 16,
|
||||||
|
child: Text(
|
||||||
|
'Offset: ${widget.controller.offset.coord()}\nScale: ${widget.controller.scale.toStringAsFixed(1)}',
|
||||||
|
style: monospaceStyle,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return canvas;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -217,7 +234,6 @@ class _CanvasRenderBox extends RenderBox
|
|||||||
childParentData.id = _childrenIds[index];
|
childParentData.id = _childrenIds[index];
|
||||||
childParentData.scale = _scale;
|
childParentData.scale = _scale;
|
||||||
index++;
|
index++;
|
||||||
// loosen so like a stack can take it's own size inside parent
|
|
||||||
child.layout(constraints.loosen(), parentUsesSize: true);
|
child.layout(constraints.loosen(), parentUsesSize: true);
|
||||||
|
|
||||||
// notify the controller about the size of the child
|
// notify the controller about the size of the child
|
||||||
|
|||||||
Reference in New Issue
Block a user