Flutter 動畫鼻祖之CustomPaint
阿新 • • 發佈:2020-06-03
![](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