Skip to content

Commit a01bea5

Browse files
Merge pull request flutter-clutter#4 from flutter-clutter/magnifier
Implement magnifier that enlarges the area around the touch bubble on panDown
2 parents a574c5f + 416e20a commit a01bea5

File tree

4 files changed

+268
-86
lines changed

4 files changed

+268
-86
lines changed

example/lib/edge_detection_shape/animated_touch_bubble_part.dart

+27-27
Original file line numberDiff line numberDiff line change
@@ -23,18 +23,18 @@ class _AnimatedTouchBubblePartState extends State<AnimatedTouchBubblePart> with
2323
);
2424

2525
_sizeAnimation = Tween<double>(
26-
begin: 0.5,
27-
end: 1.0
26+
begin: 0.5,
27+
end: 1.0
2828
).animate(_controller);
2929

3030
_colorAnimation = ColorTween(
31-
begin: Theme.of(context).accentColor.withOpacity(0.5),
32-
end: Theme.of(context).accentColor.withOpacity(0.0)
31+
begin: Theme.of(context).accentColor.withOpacity(0.5),
32+
end: Theme.of(context).accentColor.withOpacity(0.0)
3333
).animate(
34-
CurvedAnimation(
35-
parent: _controller,
36-
curve: Interval(0.5, 1.0)
37-
)
34+
CurvedAnimation(
35+
parent: _controller,
36+
curve: Interval(0.5, 1.0)
37+
)
3838
);
3939

4040
_controller.repeat();
@@ -53,31 +53,31 @@ class _AnimatedTouchBubblePartState extends State<AnimatedTouchBubblePart> with
5353
children: [
5454
Center(
5555
child: Container(
56-
width: widget.dragging ? widget.size : widget.size / 2,
57-
height: widget.dragging ? widget.size : widget.size / 2,
56+
width: widget.dragging ? 0 : widget.size / 2,
57+
height: widget.dragging ? 0 : widget.size / 2,
5858
decoration: BoxDecoration(
59-
color: Theme.of(context).accentColor.withOpacity(0.5),
60-
borderRadius: widget.dragging ? BorderRadius.circular(widget.size) : BorderRadius.circular(widget.size / 4)
59+
color: Theme.of(context).accentColor.withOpacity(0.5),
60+
borderRadius: widget.dragging ? BorderRadius.circular(widget.size) : BorderRadius.circular(widget.size / 4)
6161
)
6262
)
6363
),
6464
AnimatedBuilder(
65-
builder: (BuildContext context, Widget child) {
66-
return Center(
67-
child: Container(
68-
width: widget.dragging ? 0 : widget.size * _sizeAnimation.value,
69-
height: widget.dragging ? 0 : widget.size * _sizeAnimation.value,
70-
decoration: BoxDecoration(
71-
border: Border.all(
72-
color: _colorAnimation.value,
73-
width: widget.size / 20
74-
),
75-
borderRadius: widget.dragging ? BorderRadius.zero : BorderRadius.circular(widget.size * _sizeAnimation.value / 2)
76-
)
65+
builder: (BuildContext context, Widget child) {
66+
return Center(
67+
child: Container(
68+
width: widget.dragging ? 0 : widget.size * _sizeAnimation.value,
69+
height: widget.dragging ? 0 : widget.size * _sizeAnimation.value,
70+
decoration: BoxDecoration(
71+
border: Border.all(
72+
color: _colorAnimation.value,
73+
width: widget.size / 20
74+
),
75+
borderRadius: widget.dragging ? BorderRadius.zero : BorderRadius.circular(widget.size * _sizeAnimation.value / 2)
7776
)
78-
);
79-
},
80-
animation: _controller
77+
)
78+
);
79+
},
80+
animation: _controller
8181
)
8282
],
8383
);

example/lib/edge_detection_shape/edge_detection_shape.dart

+88-39
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import 'package:flutter/material.dart';
55
import 'package:simple_edge_detection/edge_detection.dart';
66

77
import 'edge_painter.dart';
8+
import 'magnifier.dart';
89
import 'touch_bubble.dart';
910

1011
class EdgeDetectionShape extends StatefulWidget {
@@ -33,10 +34,12 @@ class _EdgeDetectionShapeState extends State<EdgeDetectionShape> {
3334
double top;
3435
double left;
3536

37+
Offset currentDragPosition;
38+
3639
@override
3740
void didChangeDependencies() {
3841
double shortestSide = min(MediaQuery.of(context).size.width, MediaQuery.of(context).size.height);
39-
edgeDraggerSize = shortestSide / 8;
42+
edgeDraggerSize = shortestSide / 12;
4043
super.didChangeDependencies();
4144
}
4245

@@ -50,19 +53,23 @@ class _EdgeDetectionShapeState extends State<EdgeDetectionShape> {
5053

5154
@override
5255
Widget build(BuildContext context) {
53-
return Stack(
54-
children: [
55-
_getTouchBubbles(),
56-
CustomPaint(
57-
painter: EdgePainter(
58-
points: points,
59-
color: Theme.of(context).accentColor.withOpacity(0.5)
60-
),
61-
)
62-
],
56+
return Magnifier(
57+
visible: currentDragPosition != null,
58+
position: currentDragPosition,
59+
child: Stack(
60+
children: [
61+
_getTouchBubbles(),
62+
CustomPaint(
63+
painter: EdgePainter(
64+
points: points,
65+
color: Theme.of(context).accentColor.withOpacity(0.5)
66+
)
67+
)
68+
],
69+
)
6370
);
6471
}
65-
72+
6673
void _calculateDimensionValues() {
6774
top = 0.0;
6875
left = 0.0;
@@ -85,17 +92,43 @@ class _EdgeDetectionShapeState extends State<EdgeDetectionShape> {
8592
);
8693
}
8794

95+
Offset _clampOffset(Offset givenOffset) {
96+
double absoluteX = givenOffset.dx * renderedImageWidth;
97+
double absoluteY = givenOffset.dy * renderedImageHeight;
98+
99+
return Offset(
100+
absoluteX.clamp(0.0, renderedImageWidth) / renderedImageWidth,
101+
absoluteY.clamp(0.0, renderedImageHeight) / renderedImageHeight
102+
);
103+
}
104+
88105
Widget _getTouchBubbles() {
89106
points = [
90-
Offset(left + edgeDetectionResult.topLeft.dx * renderedImageWidth, top + edgeDetectionResult.topLeft.dy * renderedImageHeight),
91-
Offset(left + edgeDetectionResult.topRight.dx * renderedImageWidth, top + edgeDetectionResult.topRight.dy * renderedImageHeight),
92-
Offset(left + edgeDetectionResult.bottomRight.dx * renderedImageWidth, top + (edgeDetectionResult.bottomRight.dy * renderedImageHeight)),
93-
Offset(left + edgeDetectionResult.bottomLeft.dx * renderedImageWidth, top + edgeDetectionResult.bottomLeft.dy * renderedImageHeight),
94-
Offset(left + edgeDetectionResult.topLeft.dx * renderedImageWidth, top + edgeDetectionResult.topLeft.dy * renderedImageHeight),
107+
Offset(
108+
left + edgeDetectionResult.topLeft.dx * renderedImageWidth,
109+
top + edgeDetectionResult.topLeft.dy * renderedImageHeight
110+
),
111+
Offset(
112+
left + edgeDetectionResult.topRight.dx * renderedImageWidth,
113+
top + edgeDetectionResult.topRight.dy * renderedImageHeight
114+
),
115+
Offset(
116+
left + edgeDetectionResult.bottomRight.dx * renderedImageWidth,
117+
top + (edgeDetectionResult.bottomRight.dy * renderedImageHeight)
118+
),
119+
Offset(
120+
left + edgeDetectionResult.bottomLeft.dx * renderedImageWidth,
121+
top + edgeDetectionResult.bottomLeft.dy * renderedImageHeight
122+
),
123+
Offset(
124+
left + edgeDetectionResult.topLeft.dx * renderedImageWidth,
125+
top + edgeDetectionResult.topLeft.dy * renderedImageHeight
126+
),
95127
];
96128

97129
final Function onDragFinished = () {
98-
setState(() {});
130+
currentDragPosition = null;
131+
setState(() {});
99132
};
100133

101134
return Container(
@@ -108,8 +141,12 @@ class _EdgeDetectionShapeState extends State<EdgeDetectionShape> {
108141
size: edgeDraggerSize,
109142
onDrag: (position) {
110143
setState(() {
111-
edgeDetectionResult.topLeft += _getNewPositionAfterDrag(
112-
position, renderedImageWidth, renderedImageHeight
144+
currentDragPosition = Offset(points[0].dx, points[0].dy);
145+
Offset newTopLeft = _getNewPositionAfterDrag(
146+
position, renderedImageWidth, renderedImageHeight
147+
);
148+
edgeDetectionResult.topLeft = _clampOffset(
149+
edgeDetectionResult.topLeft + newTopLeft
113150
);
114151
});
115152
},
@@ -123,9 +160,13 @@ class _EdgeDetectionShapeState extends State<EdgeDetectionShape> {
123160
size: edgeDraggerSize,
124161
onDrag: (position) {
125162
setState(() {
126-
edgeDetectionResult.topRight += _getNewPositionAfterDrag(
127-
position, renderedImageWidth, renderedImageHeight
163+
Offset newTopRight = _getNewPositionAfterDrag(
164+
position, renderedImageWidth, renderedImageHeight
165+
);
166+
edgeDetectionResult.topRight = _clampOffset(
167+
edgeDetectionResult.topRight + newTopRight
128168
);
169+
currentDragPosition = Offset(points[1].dx, points[1].dy);
129170
});
130171
},
131172
onDragFinished: onDragFinished
@@ -135,30 +176,38 @@ class _EdgeDetectionShapeState extends State<EdgeDetectionShape> {
135176
),
136177
Positioned(
137178
child: TouchBubble(
138-
size: edgeDraggerSize,
139-
onDrag: (position) {
140-
setState(() {
141-
edgeDetectionResult.bottomRight += _getNewPositionAfterDrag(
179+
size: edgeDraggerSize,
180+
onDrag: (position) {
181+
setState(() {
182+
Offset newBottomRight = _getNewPositionAfterDrag(
142183
position, renderedImageWidth, renderedImageHeight
143-
);
144-
});
145-
},
146-
onDragFinished: onDragFinished
184+
);
185+
edgeDetectionResult.bottomRight = _clampOffset(
186+
edgeDetectionResult.bottomRight + newBottomRight
187+
);
188+
currentDragPosition = Offset(points[2].dx, points[2].dy);
189+
});
190+
},
191+
onDragFinished: onDragFinished
147192
),
148193
left: points[2].dx - (edgeDraggerSize / 2),
149194
top: points[2].dy - (edgeDraggerSize / 2)
150195
),
151196
Positioned(
152197
child: TouchBubble(
153-
size: edgeDraggerSize,
154-
onDrag: (position) {
155-
setState(() {
156-
edgeDetectionResult.bottomLeft += _getNewPositionAfterDrag(
157-
position, renderedImageWidth, renderedImageHeight
158-
);
159-
});
160-
},
161-
onDragFinished: onDragFinished
198+
size: edgeDraggerSize,
199+
onDrag: (position) {
200+
setState(() {
201+
Offset newBottomLeft = _getNewPositionAfterDrag(
202+
position, renderedImageWidth, renderedImageHeight
203+
);
204+
edgeDetectionResult.bottomLeft = _clampOffset(
205+
edgeDetectionResult.bottomLeft + newBottomLeft
206+
);
207+
currentDragPosition = Offset(points[3].dx, points[3].dy);
208+
});
209+
},
210+
onDragFinished: onDragFinished
162211
),
163212
left: points[3].dx - (edgeDraggerSize / 2),
164213
top: points[3].dy - (edgeDraggerSize / 2)

0 commit comments

Comments
 (0)