产品经理常会提出将图片裁剪成各种形状的需求,那么在Flutter中怎样才干为所欲为的裁剪出各种形状的图片呢,本文将带领你去看看。下面是本文目录:
- ClipOval裁剪矩形会有啥不同
- ClipRRect为所欲为的裁剪出圆角
- ClipPath能够画出你能想到的一切形状
ClipOval
从类的承继关系我们能够明晰的看到ClipOval是一个承继自SingleChildRenderObjectWidget的组件,那么它只能包含一个子控件,从名字就能知道它是用来裁剪的,那么它裁剪的作用是怎样的呢?举例说明:
ClipOval(
child: Container(
color: Colors.blue,
height: 100,
width: 200,
child: mIv,
),
),
当ClipOval包裹的子控件是一个矩形时,剪切的是一个椭圆,那么当它是个正方形时会怎样呢?按照数学几何知识,椭圆长轴和短轴相等时会是一个圆,那么是不是说当子控件是一个正方形时会剪切出圆呢?
ClipOval(
child: Container(
color: Colors.blue,
height: 100,
width: 100,
child: mIv,
),
),
bingo!没有问题~经过包裹一个正方形,经过ClipOval剪切出来的便是一个圆。
自此我们能够得出结论,当ClipOval剪切时若包裹的子控件为矩形时获得的结果是一个椭圆,若此矩形为正方形时结果是一个圆,这能够作为设置圆形头像的完成计划。
ClipRRect
这个组件和ClipOval相同也是承继自SingleChildRenderObjectWidget,作用源码描绘的很清楚,便是用圆角矩形来剪切子控件的。比较简略,直接上比如:
ClipRRect(
borderRadius: BorderRadius.all(Radius.circular(10)),
child: Container(
color: Colors.blue,
height: 100,
width: 100,
child: mIv,
),
),
BorderRadius供给了多个结构办法,能够设置每个角的圆角视点。即这个控件能够剪切子控件的圆角出现。
ClipPath
从源码描绘来说,这个组件是经过设置途径来编排子控件的。那么这个途径是什么意思呢?是不是意味着不管自己设置什么样的线都能够编排出来,即设置一个旋转90度的棱形,或者画各种图案都能够呢?接下来我们来探究一下:
ClipPath的结构办法很简略,只要三个属性clipper,clipBehavior,以及SingleChildRenderObjectWidget子类都有的child。而clipBehavior是有默认值的,那么我们能够合理的推测clipper便是设置途径的属性。
我们能够看到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办法中的结尾坐标用直线连接起来。比如中将矩形的中间方位连接而成,结果便是:
path其他画线办法就不一一解释,但是其间还有两个办法值得讲解一下,便是二阶贝塞尔曲线办法quadraticBezierTo。
二阶贝塞尔曲线:
上图便是二阶贝塞尔曲线的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的坐标。作用如下:
三阶贝塞尔曲线:
上图便是三阶贝塞尔曲线的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%的方位,此刻截取的图案为:
到这儿,本文基本就结束了。总结来说,如果我们想简略的截取一个椭圆或者圆直接运用ClipOval即可,想给方方正正的矩形加圆角能够选择ClipRRect,但是如果想为所欲为的去截取图片完成各种花样那么我们能够运用ClipPath。
非常感谢大家阅读,专心才干进步学习效率,Peace!