Flutter 實現圖片裁剪


 

 

實現原理很簡單 ,自己繪制一個裁剪框, 根據手勢 選擇到適合的位置 ,然后將選中的區域繪制到一個新的圖片上,從而完成裁剪

 

裁剪框的繪制  這里我是根據點來連線的  因為每個點上會繪制一個拉伸的標識符

復制代碼
      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);
復制代碼

 

源圖片的繪制 ,根據屏幕大小  把圖片縮放成適合長寬比例的圖片

復制代碼
 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);
    }
復制代碼

 

 

繪制完后 就是根據手勢的偏移量來計算裁剪框的大小位置

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

_points有4個值    [0] 代表down的坐標   [1]代表move的左邊   [2]代表裁剪框的坐標  [3]代表源圖大小

在touchDown的時候  先存儲左邊  然后我們要計算點的區域是 拉伸 還是移動   拉伸的話是以頂點為中心的放心

復制代碼
 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;
        }

      });
    }

  }
復制代碼

 手指抬起的時候將一些坐標重置下

復制代碼
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);
    });
  }

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM