Flutter 裁剪类组件 最全总结
注意:无特殊说明,flutter版本及dart版本如下:
- flutter版本: 1.12.13+hotfix.5
- dart版本: 2.7.0
cliprect
cliprect组件使用矩形裁剪子组件,通常情况下,cliprect作用于custompaint
、 customsinglechildlayout
、 custommultichildlayout
、 align
、 center
、 overflowbox
、 sizedoverflowbox
组件,例如cliprect作用于align,可以仅显示上半部分,代码如下:
cliprect( child: align( alignment: alignment.topcenter, heightfactor: 0.5, child: container( height: 150, width: 150, child: image.asset( 'images/1.png', fit: boxfit.cover, ), ), ), )
全图效果:
裁剪效果:
clipper
参数定义裁剪规则,下面具体介绍。
clipbehavior
参数定义了裁剪的方式,只有子控件超出父控件的范围才有裁剪的说法,各个方式说明如下:
- none:不裁剪,系统默认值,如果子组件不超出边界,此值没有任何性能消耗。
- hardedge:裁剪但不应用抗锯齿,速度比
none
慢一点,但比其他方式快。 - antialias:裁剪而且抗锯齿,此方式看起来更平滑,比
antialiaswithsavelayer
快,比hardedge
慢,通常用于处理圆形和弧形裁剪。 - antialiaswithsavelayer:裁剪、抗锯齿而且有一个缓冲区,此方式很慢,用到的情况比较少。
cliprrect
cliprrect组件可以对子组件进行圆角裁剪,默认圆角半径为0,注意cliprrect有2个r,不是上面介绍的cliprect。
用法如下:
cliprrect( borderradius: borderradius.circular(20), child: container( height: 150, width: 150, child: image.asset( 'images/1.png', fit: boxfit.cover, ), ), )
效果如图:
clipoval
clipoval裁剪为椭圆形,椭圆形的大小为正切父组件,因此如果父组件为正方形,切出来是圆形,用法如下:
clipoval( child: container( height: 150, width: 250, child: image.asset( 'images/1.png', fit: boxfit.cover, ), ), )
效果如下:
clippath
clippath组件根据路径进行裁剪,我们自定义裁剪路径也可以使用系统提供的,用法如下:
clippath.shape( shape: stadiumborder(), child: container( height: 150, width: 250, child: image.asset( 'images/1.png', fit: boxfit.cover, ), ), )
shape
参数是shapeborder类型,系统已经定义了很多形状,介绍如下:
roundedrectangleborder:圆角矩形
continuousrectangleborder:直线和圆角平滑连续的过渡,和roundedrectangleborder相比,圆角效果会小一些。
stadiumborder:类似于足球场的形状,两端半圆。
beveledrectangleborder:斜角矩形。效果如图:
- circleborder:圆形。
customclipper
customclipper并不是一个组件,而是一个abstract
(抽象)类,使用customclipper可以绘制出任何我们想要的形状,比如三角形,代码如下:
@override widget build(buildcontext context) { return center( child: clippath( clipper: trianglepath(), child: container( height: 150, width: 250, child: image.asset( 'images/1.png', fit: boxfit.cover, ), ), ), ); }
自定义trianglepath代码如下:
class trianglepath extends customclipper<path>{ @override path getclip(size size) { var path = path(); path.moveto(size.width/2, 0); path.lineto(0, size.height); path.lineto(size.width, size.height); return path; } @override bool shouldreclip(customclipper<path> oldclipper) { return true; } }
效果如下:
我们还可以绘制五角星,代码如下:
class starpath extends customclipper<path> { starpath({this.scale = 2.5}); final double scale; double perdegree = 36; /// 角度转弧度公式 double degree2radian(double degree) { return (pi * degree / 180); } @override path getclip(size size) { var r = min(size.width / 2, size.height / 2); var r = r / scale; var x = size.width / 2; var y = size.height / 2; var path = path(); path.moveto(x, y - r); path.lineto(x - sin(degree2radian(perdegree)) * r, y - cos(degree2radian(perdegree)) * r); path.lineto(x - sin(degree2radian(perdegree * 2)) * r, y - cos(degree2radian(perdegree * 2)) * r); path.lineto(x - sin(degree2radian(perdegree * 3)) * r, y - cos(degree2radian(perdegree * 3)) * r); path.lineto(x - sin(degree2radian(perdegree * 4)) * r, y - cos(degree2radian(perdegree * 4)) * r); path.lineto(x - sin(degree2radian(perdegree * 5)) * r, y - cos(degree2radian(perdegree * 5)) * r); path.lineto(x - sin(degree2radian(perdegree * 6)) * r, y - cos(degree2radian(perdegree * 6)) * r); path.lineto(x - sin(degree2radian(perdegree * 7)) * r, y - cos(degree2radian(perdegree * 7)) * r); path.lineto(x - sin(degree2radian(perdegree * 8)) * r, y - cos(degree2radian(perdegree * 8)) * r); path.lineto(x - sin(degree2radian(perdegree * 9)) * r, y - cos(degree2radian(perdegree * 9)) * r); path.lineto(x - sin(degree2radian(perdegree * 10)) * r, y - cos(degree2radian(perdegree * 10)) * r); return path; } @override bool shouldreclip(starpath oldclipper) { return oldclipper.scale != this.scale; } }
scale
参数表示间隔的点到圆心的缩放比例,五角星效果如下:
下面用动画动态设置scale
,代码如下:
class startclip extends statefulwidget { @override state<statefulwidget> createstate() => _startclipstate(); } class _startclipstate extends state<startclip> with singletickerproviderstatemixin { animationcontroller _controller; animation _animation; @override void initstate() { _controller = animationcontroller(duration: duration(seconds: 2), vsync: this) ..addstatuslistener((status) { if (status == animationstatus.completed) { _controller.reverse(); } else if (status == animationstatus.dismissed) { _controller.forward(); } }); _animation = tween(begin: 1.0, end: 4.0).animate(_controller); _controller.forward(); super.initstate(); } @override widget build(buildcontext context) { return center( child: animatedbuilder( animation: _animation, builder: (context, child) { return clippath( clipper: starpath(scale: _animation.value), child: container( height: 150, width: 150, color: colors.red, ), ); }), ); } }
效果如下:
今天的文章对大家是否有帮助?如果有,请在文章底部留言和点赞,你们的留言、点赞和转发关注是我持续更新的动力!
欢迎您的加入flutter的微信交流群(mqd_zzy),欢迎您的加入,让我们一起学习,一起进步,开始我们的故事,生活不止眼前的苟且,还有诗和《远方》。
当然我也非常希望您关注我个人的公众号,里面有各种福利等着大家哦。