1. 程式人生 > >Flutter 動畫鼻祖之CustomPaint

Flutter 動畫鼻祖之CustomPaint

![](https://img2020.cnblogs.com/other/467322/202006/467322-20200602220753010-1077465192.png) > 老孟導讀:CustomPaint可以稱之為動畫鼻祖,它可以實現任何酷炫的動畫和效果。CustomPaint本身沒有動畫屬性,僅僅是繪製屬性,一般情況下,CustomPaint會和動畫控制配合使用,達到理想的效果。 ## 基本用法 CustomPaint的用法非常簡單,如下: ```dart CustomPaint( painter: MyCustomPainter(), ) ``` MyCustomPainter定義如下: ```dart class MyCustomPainter extends CustomPainter { @override void paint(Canvas canvas, Size size) {} @override bool shouldRepaint(MyCustomPainter oldDelegate) { return this != oldDelegate; } } ``` 上面的MyCustomPainter為了看起來清晰,什麼也沒有做,通常情況下,在`paint`方法內繪製自定義的效果。`shouldRepaint`方法通常在當前例項和舊例項屬性不一致時返回true。 `paint`通過`canvas`繪製,`size`為當前控制元件的大小,下面看看`canvas`的方法。 ### 繪製點 ```dart Paint _paint = Paint() ..color = Colors.red ..strokeWidth = 3; @override void paint(Canvas canvas, Size size) { var points = [ Offset(0, 0), Offset(size.width / 2, size.height / 2), Offset(size.width, size.height), ]; canvas.drawPoints(PointMode.points, points, _paint); } ``` ![image-20200601094814789](https://img2020.cnblogs.com/other/467322/202006/467322-20200602220753467-262596316.png) `PointMode`有3種模式: - points:點 - lines:將2個點繪製為線段,如果點的個數為奇數,最後一個點將會被忽略 - polygon:將整個點繪製為一條線 ### 繪製線 ```dart canvas.drawLine(Offset(0, 0),Offset(size.width, size.height), _paint); ``` ![image-20200601095248302](https://img2020.cnblogs.com/other/467322/202006/467322-20200602220753674-688071593.png) ### 繪製路徑 ```dart Paint _paint = Paint() ..color = Colors.red ..style = PaintingStyle.stroke ..strokeWidth = 3; @override void paint(Canvas canvas, Size size) { print('size:$size'); var _path = Path() ..moveTo(0, 0) ..lineTo(size.width, 0) ..lineTo(size.width, size.height) ..close(); canvas.drawPath(_path, _paint); } ``` ![image-20200601110532164](https://img2020.cnblogs.com/other/467322/202006/467322-20200602220753921-1474446743.png) 這裡注意`Paint.style`,還可以設定為`PaintingStyle.fill`,效果如下: ![image-20200601110642252](https://img2020.cnblogs.com/other/467322/202006/467322-20200602220754537-1639977608.png) 此時Path的路徑不要在一條直線上,否則會看不到效果。 ### 繪製各種形狀 繪製圓形 ```dart canvas.drawCircle(Offset(size.width/2, size.height/2), 20, _paint); ``` ![image-20200601111802952](https://img2020.cnblogs.com/other/467322/202006/467322-20200602220754894-12578961.png) 繪製橢圓 ```dart canvas.drawOval(Rect.fromLTRB(0, 0, size.width, size.height/2), _paint); ``` ![image-20200601111910120](https://img2020.cnblogs.com/other/467322/202006/467322-20200602220755337-284719872.png) 如果給定的Rect為正方形,那麼橢圓將會變為圓形。 繪製弧 ```dart canvas.drawArc( Rect.fromLTRB(0, 0, size.width, size.height), 0, pi/2, true, _paint); ``` ![image-20200601112255715](https://img2020.cnblogs.com/other/467322/202006/467322-20200602220755882-602707424.png) 繪製圓角矩形 ```dart canvas.drawRRect( RRect.fromLTRBR(0, 0, size.width, size.height, Radius.circular(10)), _paint) ``` ![image-20200601112830212](https://img2020.cnblogs.com/other/467322/202006/467322-20200602220756290-326686518.png) `canvas`還有很多繪製函式,比如貝塞爾曲線、三次貝塞爾曲線、畫布的反轉等操作,這裡不在一一介紹。 **這些函式和Android的Canvas基本一樣,如果你有Android基礎,直接套用即可。** 最後奉上一個繪製玫瑰的動畫效果: ![rose_gif](https://img2020.cnblogs.com/other/467322/202006/467322-20200602220756943-2142782376.gif) 這個效果是不是很酷炫,我們看下繪製花骨朵程式碼: ```dart /// /// 繪製花骨朵 /// _drawFlower(Canvas canvas, Size size) { //將花變為紅色 if (flowerPaths.length >= RoseData.flowerPoints.length) { var path = Path(); for (int i = 0; i < flowerPaths.length; i++) { if (i == 0) { path.moveTo(flowerPaths[i].dx, flowerPaths[i].dy); } else { path.lineTo(flowerPaths[i].dx, flowerPaths[i].dy); } } _paint.style = PaintingStyle.fill; _paint.color = _flowerColor; canvas.drawPath(path, _paint); } //繪製線 _paint.style = PaintingStyle.stroke; _paint.color = _strokeColor; //去掉最後2個點,最後2個點為了繪製紅色 var points = flowerPaths.sublist(0, max(0, flowerPaths.length - 2)); canvas.drawPoints(PointMode.polygon, points, _paint); } ``` 花骨朵的繪製只通過`canvas.drawPath`就實現了,其實整個玫瑰花的繪製都是通過`canvas.drawPath`加上動畫控制實現的。 CustomPaint可以實現任何你想要的動畫的效果,比如繪畫版就可以通過此控制元件實現。 獲取完整程式碼方式掃碼下方二維碼回覆:rose ![](https://img2020.cnblogs.com/other/467322/202006/467322-20200602220757215-1561806494.jpg) ## 交流 老孟Flutter部落格地址(近200個控制元件用法):[http://laomengit.com](http://laomengit.com) 歡迎加入Flutter交流群(微信:laomengit)、關注公眾號【老孟Flutter】: | | | | ----------------------------------------------- | ------------------------------------------------------------ | | ![](https://img2020.cnblogs.com/other/467322/202006/467322-20200602220757773-758422490.png) | ![](https://img2020.cnblogs.com/other/467322/202006/467322-20200602220758336-1501465240