現在人們對於網站的美感要求是越來越高了,所以很多布局需要優美的曲線設計。當然最簡單的辦法是作一個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
方法里,它返回一段路徑。
一個二階的貝塞爾曲線是需要控制點和終點的,控制點就像一塊磁鐵,把直線吸引過去,形成一個完美的弧度,這個弧度就是貝塞爾曲線了。
我們先來熟悉一下裁切路徑和貝塞爾曲線,作一個最簡單的貝塞爾曲線出來。
全部代碼如下:
import 'package:flutter/material.dart'; class CustomClipperDemo extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', debugShowCheckedModeBanner: false, //去掉debug圖標 theme: ThemeData( primarySwatch: Colors.red ), home: CurvePage(), ); } } 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, ), ), ], ), ); } } class BottomClipper extends CustomClipper<Path>{ @override Path getClip(Size size){ var path = Path(); path.lineTo(0, 0); //第1個點 path.lineTo(0, size.height-50.0); //第2個點 var firstControlPoint = Offset(size.width/2, size.height); var firstEdnPoint = Offset(size.width, size.height-50.0); path.quadraticBezierTo( firstControlPoint.dx, firstControlPoint.dy, firstEdnPoint.dx, firstEdnPoint.dy ); path.lineTo(size.width, size.height-50.0); //第3個點 path.lineTo(size.width, 0); //第4個點 return path; } @override bool shouldReclip(CustomClipper<Path> oldClipper) { return false; } }
波浪形式的貝塞爾曲線
在上面代碼的基礎上修改為波浪式的貝塞爾曲線,波浪形式的只要把裁切變成兩個對稱的貝塞爾曲線就可以實現了。
代碼如下:
//曲線路徑 class BottomClipper extends CustomClipper<Path>{ @override Path getClip(Size size){ var path = Path(); //定義路徑 //path.lineTo(0, 0); //第1個點 //path.lineTo(0, size.height-50.0); //第2個點 //var firstControlPoint = Offset(size.width/2, size.height); //第一段曲線控制點 //var firstEdnPoint = Offset(size.width, size.height-50.0); //第一段曲線結束點 //path.quadraticBezierTo( //形成曲線 // firstControlPoint.dx, // firstControlPoint.dy, // firstEdnPoint.dx, // firstEdnPoint.dy //); //path.lineTo(size.width, size.height-50.0); //第3個點 //path.lineTo(size.width, 0); //第4個點 //波浪曲線路徑 path.lineTo(0, 0); //第1個點 path.lineTo(0, size.height - 40.0); //第2個點 var firstControlPoint = Offset(size.width/4, size.height); //第一段曲線控制點 var firstEndPoint = Offset(size.width/2.25, size.height-30); //第一段曲線結束點 path.quadraticBezierTo( //形成曲線 firstControlPoint.dx, firstControlPoint.dy, firstEndPoint.dx, firstEndPoint.dy); var secondControlPoint = Offset(size.width/4*3, size.height-90); //第二段曲線控制點 var secondEndPoint = Offset(size.width, size.height-40); //第二段曲線結束點 path.quadraticBezierTo( //形成曲線 secondControlPoint.dx, secondControlPoint.dy, secondEndPoint.dx, secondEndPoint.dy); path.lineTo(size.width, size.height-40); path.lineTo(size.width, 0); return path; } @override bool shouldReclip(CustomClipper<Path> oldClipper) { return false; } }