diff --git a/lib/my_flutter_drag_scale/lib/core/touchable_container.dart b/lib/my_flutter_drag_scale/lib/core/touchable_container.dart index 3305049..a97c870 100644 --- a/lib/my_flutter_drag_scale/lib/core/touchable_container.dart +++ b/lib/my_flutter_drag_scale/lib/core/touchable_container.dart @@ -1,3 +1,5 @@ +import 'dart:math'; + import 'package:flutter/material.dart'; import './custom_gesture_detector.dart' as gd; @@ -51,7 +53,7 @@ class _TouchableContainerState extends State @override void initState() { super.initState(); - _controller = new AnimationController(vsync: this)..addListener(_handleFlingAnimation); + _controller = AnimationController(vsync: this)..addListener(_handleFlingAnimation); } @override @@ -65,8 +67,30 @@ class _TouchableContainerState extends State //也就是最小值是原点0,0,点从最大值到0的区间,也就是这个图可以从最大值移动到原点 Offset _clampOffset(Offset offset) { final Size size = context.size; //容器的大小 - final Offset minOffset = new Offset(size.width, size.height) * (1.0 - _scale); - return new Offset(offset.dx.clamp(minOffset.dx, 0.0), offset.dy.clamp(minOffset.dy, 0.0)); + // print("context.size = ${context.size}"); // context.size = Size(298.0, 298.0) + final Offset minOffset = Offset(size.width, size.height) * (1.0 - _scale); + return Offset(offset.dx.clamp(minOffset.dx, 0.0), offset.dy.clamp(minOffset.dy, 0.0)); + // return Offset(minOffset.dx / 2, minOffset.dy / 2); + } + + // 实现双击图片放大后,点击位置位于容器中央 + Offset _clampOffset2(Offset position) { + final Size size = context.size; //容器的大小 + // print("context.size = ${context.size}"); // context.size = Size(298.0, 298.0) + RenderBox renderBox = context.findRenderObject(); + Offset offsetTopLeft = renderBox.localToGlobal(Offset.zero); + print("offsetTopLeft = $offsetTopLeft"); // offsetTopLeft = Offset(31.0, 111.0) + + double x = position.dx - offsetTopLeft.dx; + x = max(x * _scale - size.width * _scale / 4, 0); + x = min(x, size.width * _scale / 2); + + double y = position.dy - offsetTopLeft.dy; + y = max(y * _scale - size.height * _scale / 4, 0); + y = min(y, size.height * _scale / 2); + print("Offset(x, y) = ${Offset(-x, -y)}"); + + return Offset(-x, -y); } void _handleFlingAnimation() { @@ -92,7 +116,7 @@ class _TouchableContainerState extends State // Ensure that image location under the focal point stays in the same place despite scaling. _offset = _clampOffset(details.focalPoint - _normalizedOffset * _scale); }); - ScaleChangedModel model = new ScaleChangedModel(scale: _scale, offset: _offset); + ScaleChangedModel model = ScaleChangedModel(scale: _scale, offset: _offset); if (widget.scaleChangedCallback != null) widget.scaleChangedCallback(model); } @@ -102,7 +126,7 @@ class _TouchableContainerState extends State final Offset direction = details.velocity.pixelsPerSecond / magnitude; final double distance = (Offset.zero & context.size).shortestSide; _flingAnimation = - new Tween(begin: _offset, end: _clampOffset(_offset + direction * distance)) + Tween(begin: _offset, end: _clampOffset(_offset + direction * distance)) .animate(_controller); _controller ..value = 0.0 @@ -111,33 +135,41 @@ class _TouchableContainerState extends State void _onDoubleTap(gd.DoubleDetails details) { _normalizedOffset = (details.pointerEvent.position - _offset) / _scale; + print("_scale = ${_scale}, _offset = ${_offset}"); + print("position = ${details.pointerEvent.position}, _normalizedOffset = ${_normalizedOffset}"); + // _scale = 1.0, _offset = Offset(0.0, 0.0) + // position = Offset(178.0, 260.7), _normalizedOffset = Offset(178.0, 260.7) if (!widget.doubleTapStillScale && _scale != 1.0) { setState(() { _scale = 1.0; _offset = Offset.zero; }); - ScaleChangedModel model = new ScaleChangedModel(scale: _scale, offset: _offset); + ScaleChangedModel model = ScaleChangedModel(scale: _scale, offset: _offset); if (widget.scaleChangedCallback != null) widget.scaleChangedCallback(model); return; } setState(() { if (widget.doubleTapStillScale) { _scale *= (1 + 0.5); + // Ensure that image location under the focal point stays in the same place despite scaling. + // _offset = doubleDownPositon; + _offset = _clampOffset(details.pointerEvent.position - _normalizedOffset * _scale); } else { _scale *= (2); + _offset = _clampOffset2(details.pointerEvent.position); + // _offset = Offset.zero; // 对齐左上角 + print("_scale = ${_scale}, _offset = ${_offset}"); + // _scale = 2.0, _offset = Offset(-175.3, -270.0) } - // Ensure that image location under the focal point stays in the same place despite scaling. - // _offset = doubleDownPositon; - _offset = _clampOffset(details.pointerEvent.position - _normalizedOffset * _scale); }); - ScaleChangedModel model = new ScaleChangedModel(scale: _scale, offset: _offset); + ScaleChangedModel model = ScaleChangedModel(scale: _scale, offset: _offset); if (widget.scaleChangedCallback != null) widget.scaleChangedCallback(model); } @override Widget build(BuildContext context) { - return new gd.GestureDetector( + return gd.GestureDetector( // onPanDown: _onPanDown, onDoubleTap: _onDoubleTap, onScaleStart: _handleOnScaleStart, @@ -151,8 +183,8 @@ class _TouchableContainerState extends State minWidth: double.maxFinite, minHeight: double.infinity, ), - child: new Transform( - transform: new Matrix4.identity() + child: Transform( + transform: Matrix4.identity() ..translate(_offset.dx, _offset.dy) ..scale(_scale, _scale, 1.0), child: widget.child),