github地址git
實現原理很簡單 ,本身繪製一個裁剪框, 根據手勢 選擇到適合的位置 ,而後將選中的區域繪製到一個新的圖片上,從而完成裁剪github
裁剪框的繪製 這裏我是根據點來連線的 由於每一個點上會繪製一個拉伸的標識符canvas
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);
源圖片的繪製 ,根據屏幕大小 把圖片縮放成適合長寬比例的圖片spa
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); }
繪製完後 就是根據手勢的偏移量來計算裁剪框的大小位置3d
GestureDetector(
onPanDown: onPanDown,
onPanUpdate:onPanUpdate,
onPanEnd: onPanEnd,
),
List<Offset> _points = <Offset>[];
_points有4個值 [0] 表明down的座標 [1]表明move的左邊 [2]表明裁剪框的座標 [3]表明源圖大小code
在touchDown的時候 先存儲左邊 而後咱們要計算點的區域是 拉伸 仍是移動 拉伸的話是以頂點爲中心的放心blog
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; } }); }
移動的時候 由於 4個點的處理邏輯是不同的 因此須要單獨判斷 這裏也作了個最小區域圖片
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; } }); } }
手指擡起的時候將一些座標重置下ip
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); }); }