实现原理很简单 ,自己绘制一个裁剪框, 根据手势 选择到适合的位置 ,然后将选中的区域绘制到一个新的图片上,从而完成裁剪

Flutter 实现图片裁剪-LMLPHPFlutter 实现图片裁剪-LMLPHPFlutter 实现图片裁剪-LMLPHP

裁剪框的绘制  这里我是根据点来连线的  因为每个点上会绘制一个拉伸的标识符

Flutter 实现图片裁剪-LMLPHP
      List<Offset> points2 = [
Offset(startX, startY),
Offset(startX + cWidth, startY),
Offset(startX + cWidth, startY + cHeight),
Offset(startX, startY + cHeight),
Offset(startX, startY),
];
canvas.drawPoints(PointMode.polygon, points2, paint);//draw the clip box
paint.color = Colors.red;
// paint..style=PaintingStyle.stroke;
double radius = 10;
canvas.drawCircle(points2[0],radius,paint); //draw the drag point
canvas.drawCircle(points2[1],radius,paint);
canvas.drawCircle(points2[2],radius,paint);
// canvas.drawLine(Offset(points2[2].dx-radius, points2[2].dy-radius), Offset(points2[2].dx+radius, points2[2].dy+radius), paint);
canvas.drawCircle(points2[3],radius,paint);
Flutter 实现图片裁剪-LMLPHP

源图片的绘制 ,根据屏幕大小  把图片缩放成适合长宽比例的图片

Flutter 实现图片裁剪-LMLPHP
 if (image != null) {
//draw the backgroud image
double dwidth = 0;
double dheight = 0;
if (image.width.toDouble() / width > image.height.toDouble() / height) {
dwidth = width;
dheight = image.height.toDouble() * dwidth / image.width.toDouble();
}
else {
dheight = height;
dwidth = image.width.toDouble() * dheight / image.height.toDouble();
}
if (points.length > 0) {
points[3] = Offset(dwidth, dheight);
}
canvas.drawImageRect(image,
Rect.fromLTWH(0, 0, image.width.toDouble(), image.height.toDouble()),
Rect.fromLTWH((width - dwidth) / 2,
(height - dheight) / 2, dwidth, dheight), paint);
}
Flutter 实现图片裁剪-LMLPHP

绘制完后 就是根据手势的偏移量来计算裁剪框的大小位置

        GestureDetector(
onPanDown: onPanDown,
onPanUpdate:onPanUpdate,
onPanEnd: onPanEnd,
),
 List<Offset> _points = <Offset>[];

_points有4个值    [0] 代表down的坐标   [1]代表move的左边   [2]代表裁剪框的坐标  [3]代表源图大小

在touchDown的时候  先存储左边  然后我们要计算点的区域是 拉伸 还是移动   拉伸的话是以顶点为中心的放心

Flutter 实现图片裁剪-LMLPHP
 onPanDown(DragDownDetails details){
RenderBox referenceBox = context.findRenderObject();
Offset localPosition =
referenceBox.globalToLocal(details.globalPosition);
setState(() {
if(_points.length<3){
_points.add(localPosition);
_points.add(localPosition);
_points.add(Offset(0, 0));
_points.add(Offset(0, 0));
}
else{
_points[0]=localPosition;
_points[1]=localPosition;
}
dHeight = cHeight;
dWidth = cWidth;
double radius = 20;
if(hitPoint(Offset(_points[2].dx+cWidth, _points[2].dy+cHeight),radius , localPosition)){
downPosition =DownPosition.RIGHT_DOWN;
isDrag = false;
}
else if(hitPoint(Offset(_points[2].dx+cWidth, _points[2].dy),radius , localPosition)){
downPosition =DownPosition.RIGHT_UP;
isDrag = false;
}
else if(hitPoint(Offset(_points[2].dx, _points[2].dy+cHeight),radius , localPosition)){
downPosition =DownPosition.LEFT_DOWN;
isDrag = false;
}
else if(hitPoint(_points[2],radius , localPosition)){
downPosition =DownPosition.LEFT_UP;
isDrag = false;
} });
}
Flutter 实现图片裁剪-LMLPHP

移动的时候  因为 4个点的处理逻辑是不一样的 所以需要单独判断 这里也做了个最小区域

Flutter 实现图片裁剪-LMLPHP
 onPanUpdate(DragUpdateDetails details) {
RenderBox referenceBox = context.findRenderObject();
Offset localPosition =
referenceBox.globalToLocal(details.globalPosition);
if(isDrag){
setState(() {
_points[1]=localPosition;
});
}
else{
setState(() {
if(downPosition==DownPosition.RIGHT_DOWN){
cWidth = dWidth+localPosition.dx - _points[1].dx;
cHeight = dHeight +localPosition.dy-_points[1].dy;
}
else if(downPosition==DownPosition.LEFT_UP){
cWidth = dWidth-(localPosition.dx - _points[1].dx);
cHeight = dHeight-(localPosition.dy-_points[1].dy);
_points[2]=localPosition;
}
else if(downPosition==DownPosition.RIGHT_UP){
cWidth = dWidth+localPosition.dx - _points[1].dx;
cHeight = dHeight-(localPosition.dy-_points[1].dy);
_points[2]=Offset(_points[2].dx, localPosition.dy);
}
else if(downPosition==DownPosition.LEFT_DOWN){
cWidth = dWidth-(localPosition.dx - _points[1].dx);
cHeight = dHeight +localPosition.dy-_points[1].dy;
_points[2]=Offset(localPosition.dx, _points[2].dy);
}
if(cWidth<20){
cWidth=20;
};
if(cHeight<20){
cHeight=20;
} });
} }
Flutter 实现图片裁剪-LMLPHP

手指抬起的时候将一些坐标重置下

Flutter 实现图片裁剪-LMLPHP
onPanEnd(DragEndDetails details){
setState(() {
isDrag = true;
double startX = _points[1].dx - _points[0].dx+_points[2].dx;
double startY = _points[1].dy - _points[0].dy+_points[2].dy;
if(startX<0)
startX = 0;
else if(startX+cWidth>width){
startX = width-cWidth;
}
if(startY<0)
startY=0;
else if(startY + cHeight>height){
startY = height-cHeight;
}
_points[0]=Offset(0, 0);
_points[1]=Offset(0, 0);
_points[2] = Offset(startX<0?0:startX, startY<0?0:startY);
});
}
 
05-26 11:05