gpt4 book ai didi

flutter CustomPaint 和 GestureDetector 都调整到图像大小

转载 作者:行者123 更新时间:2023-12-03 02:46:46 27 4
gpt4 key购买 nike

我想让用户有机会在 CustomPaint 上使用手机创建多边形。对于此功能,还涉及 GestureDetector。正在使用 ImagePicker 库从文件加载图像。这里的问题是如何将 Canvas 和手势检测器调整为图片的大小。有什么想法吗?

Code: `import 'dart:io';
import 'dart:math';
import 'dart:ui' as ui;

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:image_picker/image_picker.dart';
import 'package:listassist/services/auth.dart';

class PictureShow extends StatefulWidget {
@override
_PictureShowState createState() => _PictureShowState();
}

class _PictureShowState extends State<PictureShow> {
ui.Image _image;
Image _imageWidget;
List<ui.Offset> _points = [ui.Offset(90, 120), ui.Offset(90, 370), ui.Offset(320, 370), ui.Offset(320, 120)];
bool _clear = false;
int _currentlyDraggedIndex = -1;

@override
Widget build(BuildContext context) {
final AppBar appBar = AppBar(
backgroundColor: Theme.of(context).colorScheme.primary,
title: Text("Rechungserkennung"),
);

return Scaffold(
floatingActionButton:
FloatingActionButton(
child: Icon(Icons.clear),
onPressed: () {
setState(() {
_clear = true;
_points = [];
});
}
),
appBar: appBar,
backgroundColor: _imageWidget != null ? Colors.black : Colors.white,
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
if (_imageWidget == null) ...[
FlatButton(
onPressed: () => _pickImage(ImageSource.camera),
color: Colors.blueAccent,
padding: EdgeInsets.all(40.0),
child: Column(
children: <Widget>[
Icon(Icons.camera_alt, color: Colors.white,),
Text("Aus der Kamera", style: TextStyle(color: Colors.white),)
],
),
),
Padding(
padding: const EdgeInsets.only(top: 40, bottom: 40),
child: Text("oder", textScaleFactor: 2,),
),
FlatButton(
onPressed: () => _pickImage(ImageSource.gallery),
color: Colors.brown,
padding: EdgeInsets.all(40.0),
child: Column(
children: <Widget>[
Icon(Icons.photo, color: Colors.white,),
Text("Aus der Gallerie", style: TextStyle(color: Colors.white),)
],
),
),
],
if (_imageWidget != null) ...[
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: CustomPaint(
size: Size.fromHeight(MediaQuery.of(context).size.height - appBar.preferredSize.height),
painter: RectanglePainter(points: _points, clear: _clear, image: _image),
),
)
]
],
),
);
}

Future _pickImage(ImageSource imageSource) async {
try {
File imageFile = await ImagePicker.pickImage(source: imageSource);
ui.Image finalImg = await _load(imageFile.path);
setState(() {
_imageWidget = Image.file(imageFile);
_image = finalImg;
});
} on Exception {
ResultHandler
.showInfoSnackbar(Text("Ein Fehler ist aufgetreten beim Öffnen des Bildes. Die App benötigt Zugriff auf die Galerie"));
}
}

Future<ui.Image> _load(String asset) async {
ByteData data = await rootBundle.load(asset);
ui.Codec codec = await ui.instantiateImageCodec(data.buffer.asUint8List());
ui.FrameInfo fi = await codec.getNextFrame();
return fi.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 超出了范围。如果我记录手势检测器发出的坐标,即使在图片外部单击时,它们也高于 0。绿色边框显示它应该如何)

img

最佳答案

您可以使用 canvas.clipRect() 方法剪辑您的 Canvas:

class RectanglePainter extends CustomPainter {
//...

RectanglePainter({@required this.points, @required this.clear, @required this.image});

@override
void paint(Canvas canvas, Size size) {
//...
canvas.clipRect(Rect.fromLTWH(0, 0, size.width, size.height));
}

}

关于flutter CustomPaint 和 GestureDetector 都调整到图像大小,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58613455/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com