Flutter 形状调整大小并拖动背景图像 canvas
Flutter shape resizing and dragging over image back-grounded canvas
我想在图像背景上创建不同类型的形状(如矩形、直线或圆形)canvas 并使用角点编辑这些形状以调整大小。我怎样才能用 flutter 做到这一点?
Shapes自定义拖角与此JavaScript框架类似Fabric.js
结果应该是这样的:
我通过编写以下代码解决了这个问题:
来自 Scaffold 的代码的第一部分:
if (_imageWidget != null) ...[
FittedBox(
fit: BoxFit.fill,
child: GestureDetector(
onPanStart: (DragStartDetails details) {
// get distance from points to check if is in circle
int indexMatch = -1;
for (int i = 0; i < _points.length; i++) {
double distance = sqrt(
pow(details.localPosition.dx - _points[i].dx, 2) +
pow(details.localPosition.dy - _points[i].dy, 2));
if (distance <= 30) {
indexMatch = i;
break;
}
}
if (indexMatch != -1) {
_currentlyDraggedIndex = indexMatch;
}
},
onPanUpdate: (DragUpdateDetails details) {
if (_currentlyDraggedIndex != -1) {
setState(() {
_points = List.from(_points);
_points[_currentlyDraggedIndex] = details.localPosition;
});
}
},
onPanEnd: (_) {
setState(() {
_currentlyDraggedIndex = -1;
});
},
child: SizedBox(
width: _image.width.toDouble(),
height: _image.height.toDouble(),
child: CustomPaint(
painter: RectanglePainter(
points: _points, clear: _clear, image: _image),
),
),
),
)
]
第二部分
class RectanglePainter extends CustomPainter {
List<Offset> points;
bool clear;
final ui.Image image;
RectanglePainter(
{@required this.points, @required this.clear, @required this.image});
@override
void paint(Canvas canvas, Size size) {
final paint = Paint()
..color = Colors.red
..strokeCap = StrokeCap.square
..style = PaintingStyle.fill
..strokeWidth = 2;
final outputRect =
Rect.fromPoints(ui.Offset.zero, ui.Offset(size.width, size.height));
final Size imageSize =
Size(image.width.toDouble(), image.height.toDouble());
final FittedSizes sizes =
applyBoxFit(BoxFit.contain, imageSize, outputRect.size);
final Rect inputSubrect =
Alignment.center.inscribe(sizes.source, Offset.zero & imageSize);
final Rect outputSubrect =
Alignment.center.inscribe(sizes.destination, outputRect);
canvas.drawImageRect(image, inputSubrect, outputSubrect, paint);
if (!clear) {
final circlePaint = Paint()
..color = Colors.red
..strokeCap = StrokeCap.square
..style = PaintingStyle.fill
..blendMode = BlendMode.multiply
..strokeWidth = 2;
for (int i = 0; i < points.length; i++) {
if (i + 1 == points.length) {
canvas.drawLine(points[i], points[0], paint);
} else {
canvas.drawLine(points[i], points[i + 1], paint);
}
canvas.drawCircle(points[i], 10, circlePaint);
}
}
}
@override
bool shouldRepaint(RectanglePainter oldPainter) =>
oldPainter.points != points || clear;
}
我想在图像背景上创建不同类型的形状(如矩形、直线或圆形)canvas 并使用角点编辑这些形状以调整大小。我怎样才能用 flutter 做到这一点?
Shapes自定义拖角与此JavaScript框架类似Fabric.js
结果应该是这样的:
我通过编写以下代码解决了这个问题:
来自 Scaffold 的代码的第一部分:
if (_imageWidget != null) ...[
FittedBox(
fit: BoxFit.fill,
child: GestureDetector(
onPanStart: (DragStartDetails details) {
// get distance from points to check if is in circle
int indexMatch = -1;
for (int i = 0; i < _points.length; i++) {
double distance = sqrt(
pow(details.localPosition.dx - _points[i].dx, 2) +
pow(details.localPosition.dy - _points[i].dy, 2));
if (distance <= 30) {
indexMatch = i;
break;
}
}
if (indexMatch != -1) {
_currentlyDraggedIndex = indexMatch;
}
},
onPanUpdate: (DragUpdateDetails details) {
if (_currentlyDraggedIndex != -1) {
setState(() {
_points = List.from(_points);
_points[_currentlyDraggedIndex] = details.localPosition;
});
}
},
onPanEnd: (_) {
setState(() {
_currentlyDraggedIndex = -1;
});
},
child: SizedBox(
width: _image.width.toDouble(),
height: _image.height.toDouble(),
child: CustomPaint(
painter: RectanglePainter(
points: _points, clear: _clear, image: _image),
),
),
),
)
]
第二部分
class RectanglePainter extends CustomPainter {
List<Offset> points;
bool clear;
final ui.Image image;
RectanglePainter(
{@required this.points, @required this.clear, @required this.image});
@override
void paint(Canvas canvas, Size size) {
final paint = Paint()
..color = Colors.red
..strokeCap = StrokeCap.square
..style = PaintingStyle.fill
..strokeWidth = 2;
final outputRect =
Rect.fromPoints(ui.Offset.zero, ui.Offset(size.width, size.height));
final Size imageSize =
Size(image.width.toDouble(), image.height.toDouble());
final FittedSizes sizes =
applyBoxFit(BoxFit.contain, imageSize, outputRect.size);
final Rect inputSubrect =
Alignment.center.inscribe(sizes.source, Offset.zero & imageSize);
final Rect outputSubrect =
Alignment.center.inscribe(sizes.destination, outputRect);
canvas.drawImageRect(image, inputSubrect, outputSubrect, paint);
if (!clear) {
final circlePaint = Paint()
..color = Colors.red
..strokeCap = StrokeCap.square
..style = PaintingStyle.fill
..blendMode = BlendMode.multiply
..strokeWidth = 2;
for (int i = 0; i < points.length; i++) {
if (i + 1 == points.length) {
canvas.drawLine(points[i], points[0], paint);
} else {
canvas.drawLine(points[i], points[i + 1], paint);
}
canvas.drawCircle(points[i], 10, circlePaint);
}
}
}
@override
bool shouldRepaint(RectanglePainter oldPainter) =>
oldPainter.points != points || clear;
}