hyzp_ybqx-Commit162:优化my_flutter_drag_scale插件,实现双击图片放大后,点击位置位于容器中央
This commit is contained in:
@@ -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<TouchableContainer>
|
||||
@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<TouchableContainer>
|
||||
//也就是最小值是原点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<TouchableContainer>
|
||||
// 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<TouchableContainer>
|
||||
final Offset direction = details.velocity.pixelsPerSecond / magnitude;
|
||||
final double distance = (Offset.zero & context.size).shortestSide;
|
||||
_flingAnimation =
|
||||
new Tween<Offset>(begin: _offset, end: _clampOffset(_offset + direction * distance))
|
||||
Tween<Offset>(begin: _offset, end: _clampOffset(_offset + direction * distance))
|
||||
.animate(_controller);
|
||||
_controller
|
||||
..value = 0.0
|
||||
@@ -111,33 +135,41 @@ class _TouchableContainerState extends State<TouchableContainer>
|
||||
|
||||
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);
|
||||
} else {
|
||||
_scale *= (2);
|
||||
}
|
||||
// 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)
|
||||
}
|
||||
});
|
||||
|
||||
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<TouchableContainer>
|
||||
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),
|
||||
|
||||
Reference in New Issue
Block a user