产品经理常会提出将图片裁剪成各种形状的需求,那么在Flutter中怎样才干为所欲为的裁剪出各种形状的图片呢,本文将带领你去看看。下面是本文目录:

  • ClipOval裁剪矩形会有啥不同
  • ClipRRect为所欲为的裁剪出圆角
  • ClipPath能够画出你能想到的一切形状

ClipOval

图片剪切在Flutter中的实现

从类的承继关系我们能够明晰的看到ClipOval是一个承继自SingleChildRenderObjectWidget的组件,那么它只能包含一个子控件,从名字就能知道它是用来裁剪的,那么它裁剪的作用是怎样的呢?举例说明:

ClipOval(
  child: Container(
    color: Colors.blue,
    height: 100,
    width: 200,
    child: mIv,
  ),
),

图片剪切在Flutter中的实现
当ClipOval包裹的子控件是一个矩形时,剪切的是一个椭圆,那么当它是个正方形时会怎样呢?按照数学几何知识,椭圆长轴和短轴相等时会是一个圆,那么是不是说当子控件是一个正方形时会剪切出圆呢?

ClipOval(
  child: Container(
    color: Colors.blue,
    height: 100,
    width: 100,
    child: mIv,
  ),
),

图片剪切在Flutter中的实现

bingo!没有问题~经过包裹一个正方形,经过ClipOval剪切出来的便是一个圆。

自此我们能够得出结论,当ClipOval剪切时若包裹的子控件为矩形时获得的结果是一个椭圆,若此矩形为正方形时结果是一个圆,这能够作为设置圆形头像的完成计划。

ClipRRect

图片剪切在Flutter中的实现
这个组件和ClipOval相同也是承继自SingleChildRenderObjectWidget,作用源码描绘的很清楚,便是用圆角矩形来剪切子控件的。比较简略,直接上比如:

ClipRRect(
  borderRadius: BorderRadius.all(Radius.circular(10)),
  child: Container(
    color: Colors.blue,
    height: 100,
    width: 100,
    child: mIv,
  ),
),

图片剪切在Flutter中的实现

BorderRadius供给了多个结构办法,能够设置每个角的圆角视点。即这个控件能够剪切子控件的圆角出现。

ClipPath

图片剪切在Flutter中的实现
从源码描绘来说,这个组件是经过设置途径来编排子控件的。那么这个途径是什么意思呢?是不是意味着不管自己设置什么样的线都能够编排出来,即设置一个旋转90度的棱形,或者画各种图案都能够呢?接下来我们来探究一下:

ClipPath的结构办法很简略,只要三个属性clipper,clipBehavior,以及SingleChildRenderObjectWidget子类都有的child。而clipBehavior是有默认值的,那么我们能够合理的推测clipper便是设置途径的属性。

图片剪切在Flutter中的实现

我们能够看到clipper是一个 CustomClipper?属性的值,而CustomClipper是一个笼统类,那么我们能够经过承继它,然后完成它的笼统办法,像这样:

class MyCustomClipper extends CustomClipper<Path> {
  @override
  Path getClip(Size size) {
    // TODO: implement getClip
    throw UnimplementedError();
  }
  @override
  bool shouldReclip(covariant CustomClipper<Path> oldClipper) {
    // TODO: implement shouldReclip
    throw UnimplementedError();
  }

我们发现它有两个笼统办法需求完成,经过名字以及源码我们能够知道getClip便是我们能够设置途径的办法,那么我们应该怎样做呢?我们看到getClip的返回值是Path而这个类供给了很多的办法来给我们设置途径,我们来看几个:

class MyCustomClipper extends CustomClipper<Path> {
  @override
  Path getClip(Size size) {
    Path path = Path();
    //设置起始点
    path.moveTo(0, size.height * 0.5);
    //设置结尾坐标,用线将他们连起来
    path.lineTo(size.width * 0.5, size.height);
    path.lineTo(size.width, size.height*0.5);
    path.lineTo(size.width * 0.5, 0);
    path.lineTo(0, size.height * 0.5);
    return path;
  }
  @override
  bool shouldReclip(covariant CustomClipper<Path> oldClipper) {
    return true;
  }
}

path的lineto办法便是将起始点以及lineto办法中的结尾坐标用直线连接起来。比如中将矩形的中间方位连接而成,结果便是:

图片剪切在Flutter中的实现

path其他画线办法就不一一解释,但是其间还有两个办法值得讲解一下,便是二阶贝塞尔曲线办法quadraticBezierTo。

二阶贝塞尔曲线:

图片剪切在Flutter中的实现
上图便是二阶贝塞尔曲线的gif图,那么在这儿我们如何运用呢?

class MyCustomClipper extends CustomClipper<Path> {
  @override
  Path getClip(Size size) {
    Path path = Path();
    //设置起始点
    path.moveTo(0, size.height * 0.5);
    //设置结尾坐标,用线将他们连起来
    path.quadraticBezierTo(0, size.height, size.width * 0.5, size.height);
    path.lineTo(size.width, size.height * 0.5);
    path.quadraticBezierTo(size.width, 0, size.width * 0.5, 0);
    path.lineTo(0, size.height * 0.5);
    return path;
  }
  @override
  bool shouldReclip(covariant CustomClipper<Path> oldClipper) {
    return true;
  }
}

我们在左下角,以及右上角时运用二阶贝塞尔曲线来设置途径,quadraticBezierTo办法的头两个参数即二阶贝塞尔曲线的P1坐标,而起始点则是P0坐标,最终两个参数而结尾P3的坐标。作用如下:

图片剪切在Flutter中的实现

三阶贝塞尔曲线:

图片剪切在Flutter中的实现
上图便是三阶贝塞尔曲线的gif图,举个比如说明它的运用:

class MyCustomClipper extends CustomClipper<Path> {
  @override
  Path getClip(Size size) {
    Path path = Path();
    //设置起始点
    path.moveTo(0, size.height * 0.5);
    //设置结尾坐标,用线将他们连起来
    path.quadraticBezierTo(0, size.height, size.width * 0.5, size.height);
    path.lineTo(size.width, size.height * 0.5);
    path.quadraticBezierTo(size.width, 0, size.width * 0.5, 0);
    path.cubicTo(size.width * 0.5, 0, 0, 0, size.width*0.2, size.height * 0.8);
    return path;
  }
  @override
  bool shouldReclip(covariant CustomClipper<Path> oldClipper) {
    return true;
  }
}

Path中是运用cubicTo办法来完成三阶贝塞尔曲线的,而二阶类似仅仅多了一个基准点。我们将最终一根途径用三阶贝塞尔曲线来画,以子控件右上角和左上角为P1,P2,结尾为宽度20%,高度80%的方位,此刻截取的图案为:

图片剪切在Flutter中的实现

到这儿,本文基本就结束了。总结来说,如果我们想简略的截取一个椭圆或者圆直接运用ClipOval即可,想给方方正正的矩形加圆角能够选择ClipRRect,但是如果想为所欲为的去截取图片完成各种花样那么我们能够运用ClipPath。

非常感谢大家阅读,专心才干进步学习效率,Peace!