现在人们对于网站的美感要求是越来越高了,所以很多布局需要优美的曲线设计。当然最简单的办法是作一个PNG的透明图片,然后外边放一个Container.但其内容如果本身就不是图片,只是容器,这种放入图片的做法会让包体变大。其实我们完全可以使用贝塞尔曲线进行切割。

ClipPath 路径裁切控件
clipPath控件可以把其内部的子控件切割,它有两个主要属性(参数):
-
child :要切割的元素,可以是容器,图片.....
-
clipper : 切割的路径,这个要和CustomClipper对象配合使用。
class CurvePage extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text('贝塞尔曲线切割')), body: Column( children: <Widget>[ ClipPath( //路径裁切组件 clipper: BottomClipper(), //路径 child: Container( color: Colors.deepOrangeAccent, height: 200.0, ), ), ], ), ); } }
在Scaffold里放置了一个列容器,然后把ClipPath控件放到了里边,ClipPath的子元素是一个容器控件Container。BootomClipper是我们自定义的一个对象,里边主要就是切割的路径。
CustomClipper 裁切路径
我们主要的贝塞尔曲线路径就写在getClip方法里,它返回一段路径。
一个二阶的贝塞尔曲线是需要控制点和终点的,控制点就像一块磁铁,把直线吸引过去,形成一个完美的弧度,这个弧度就是贝塞尔曲线了。
我们先来熟悉一下裁切路径和贝塞尔曲线,作一个最简单的贝塞尔曲线出来。
全部代码如下:
1import 'package:flutter/material.dart'; 2 3class CustomClipperDemo extends StatelessWidget { 4 @override 5 Widget build(BuildContext context) { 6 return MaterialApp( 7 title: 'Flutter Demo', 8 debugShowCheckedModeBanner: false, //去掉debug图标 9 theme: ThemeData( 10 primarySwatch: Colors.red 11 ), 12 home: CurvePage(), 13 ); 14 } 15} 16 17class CurvePage extends StatelessWidget { 18 @override 19 Widget build(BuildContext context) { 20 return Scaffold( 21 appBar: AppBar(title: Text('贝塞尔曲线切割')), 22 body: Column( 23 children: <Widget>[ 24 ClipPath( //路径裁切组件 25 clipper: BottomClipper(), //路径 26 child: Container( 27 color: Colors.deepOrangeAccent, 28 height: 200.0, 29 ), 30 ), 31 ], 32 ), 33 ); 34 } 35} 36 37class BottomClipper extends CustomClipper<Path>{ 38 39 @override 40 Path getClip(Size size){ 41 var path = Path(); 42 path.lineTo(0, 0); //第1个点 43 path.lineTo(0, size.height-50.0); //第2个点 44 var firstControlPoint = Offset(size.width/2, size.height); 45 var firstEdnPoint = Offset(size.width, size.height-50.0); 46 path.quadraticBezierTo( 47 firstControlPoint.dx, 48 firstControlPoint.dy, 49 firstEdnPoint.dx, 50 firstEdnPoint.dy 51 ); 52 path.lineTo(size.width, size.height-50.0); //第3个点 53 path.lineTo(size.width, 0); //第4个点 54 55 return path; 56 } 57 @override 58 bool shouldReclip(CustomClipper<Path> oldClipper) { 59 return false; 60 } 61}
波浪形式的贝塞尔曲线

在上面代码的基础上修改为波浪式的贝塞尔曲线,波浪形式的只要把裁切变成两个对称的贝塞尔曲线就可以实现了。
代码如下:
1//曲线路径 2class BottomClipper extends CustomClipper<Path>{ 3 @override 4 Path getClip(Size size){ 5 var path = Path(); //定义路径 6 //path.lineTo(0, 0); //第1个点 7 //path.lineTo(0, size.height-50.0); //第2个点 8 //var firstControlPoint = Offset(size.width/2, size.height); //第一段曲线控制点 9 //var firstEdnPoint = Offset(size.width, size.height-50.0); //第一段曲线结束点 10 //path.quadraticBezierTo( //形成曲线 11 // firstControlPoint.dx, 12 // firstControlPoint.dy, 13 // firstEdnPoint.dx, 14 // firstEdnPoint.dy 15 //); 16 //path.lineTo(size.width, size.height-50.0); //第3个点 17 //path.lineTo(size.width, 0); //第4个点 18 19 //波浪曲线路径 20 path.lineTo(0, 0); //第1个点 21 path.lineTo(0, size.height - 40.0); //第2个点 22 var firstControlPoint = Offset(size.width/4, size.height); //第一段曲线控制点 23 var firstEndPoint = Offset(size.width/2.25, size.height-30); //第一段曲线结束点 24 path.quadraticBezierTo( //形成曲线 25 firstControlPoint.dx, 26 firstControlPoint.dy, 27 firstEndPoint.dx, 28 firstEndPoint.dy); 29 30 var secondControlPoint = Offset(size.width/4*3, size.height-90); //第二段曲线控制点 31 var secondEndPoint = Offset(size.width, size.height-40); //第二段曲线结束点 32 path.quadraticBezierTo( //形成曲线 33 secondControlPoint.dx, 34 secondControlPoint.dy, 35 secondEndPoint.dx, 36 secondEndPoint.dy); 37 38 path.lineTo(size.width, size.height-40); 39 path.lineTo(size.width, 0); 40 41 return path; 42 } 43 @override 44 bool shouldReclip(CustomClipper<Path> oldClipper) { 45 return false; 46 } 47}