zoukankan      html  css  js  c++  java
  • 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);
        });
      }
     
  • 相关阅读:
    SQL性能优化:如何定位网络性能问题
    ORACLE 10升级到10.2.0.5 Patch Set遇到的内核参数检测失败问题
    Linux 僵尸进程查杀
    Linux 虚拟机网络适配器从E1000改为VMXNET3
    v$session中server为none与shared值解析
    SQL SERVER导出特殊格式的平面文件
    XtraBackup出现 Can't connect to local MySQL server through socket '/tmp/mysql.sock'
    CentOS 6.6安装Xtrabackup RPM提示缺少libev.so.4()
    SQL Server Replication 中关于视图的点滴
    ORA-00988: missing or invalid password(s)
  • 原文地址:https://www.cnblogs.com/pythonClub/p/10859073.html
Copyright © 2011-2022 走看看