Flutter學習:認識CustomPaint組件和Paint對象
Flutter學習:使用CustomPaint繪制路徑
Flutter學習:使用CustomPaint繪制圖形
Flutter學習:使用CustomPaint繪制文字
Flutter學習:使用CustomPaint繪制圖片
CustomPaint
CustomPaint是flutter的一個組件,所以我們可以像其他組件一樣使用:
CustomPaint({
Key? key,
CustomPainter? painter, // 繪制在子元素的下層
CustomPainter? foregroundPainter, // 繪制在子元素的上層
Size size = Size.zero, // 約定的布局大小,有子元素就為子元素大小
bool isComplex = false, // 繪制復雜的圖形時應為 true
bool willChange = false, // 在下一幀時是否會發生改變
Widget? child, // 子元素
})
在CustomPaint中,要想自由的繪制內容,需要使用painter或foregroundPainter屬性。傳入一個自定義繼承CustomPainter的類。
在繼承CustomPainter后有兩個必須重寫的方法。在paint方法中進行繪制操作,shouldRepaint方法用來描述繪制的內容什么時候應該更新。
class MyCustomPainter extends CustomPainter {
@override
void paint(Canvas canvas, Size size) {
// TODO: implement paint
}
@override
bool shouldRepaint(covariant CustomPainter oldDelegate) => this != oldDelegate;
}
前提代碼:
class HomePage extends StatelessWidget {
const HomePage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
body: CustomPaint(
painter: MyCustomPainter(),
// 如果CustomPaint的父元素沒有指定大小
// CusotmPaint的子元素沒有指定大小
// CustomPaint的size屬性沒有指定大小
// 繪畫出來的顯示效果和有指定大小的完全不一樣
size: Size.infinite,
),
);
}
}
以下是在頁面中繪制一個寬250,高300的矩形:
Paint
Paint相當於一支畫筆,可以自定義畫筆的顏色、粗細等。首先實例化一個Paint對象:
Paint paint = Paint();
Paint類和繪制內容相關的屬性一共有14個:
style
style → PaintStyle?,是否繪制內部形狀,形狀的邊緣,或兩者都繪制
// 填充(默認)
paint.style = PaintingStyle.fill;
// 描邊
paint.style = PaintingStyle.stroke;
Color
color → Color?,描邊或填充形狀時使用的顏色。
// 默認為不透明黑色Colors.black
paint.color = Colors.red;
colorFilter
colorFilter → ColorFilter?,繪制形狀或合成圖層時應用的顏色過濾器,繪制形狀時, colorFilter會覆蓋color和shader。
// 構造一個將 sRGB 伽馬曲線應用於 RGB 通道的濾色器
paint.colorFilter = const ColorFilter.linearToSrgbGamma();
// 創建一個顏色過濾器,將 sRGB 伽馬曲線的倒數應用於 RGB 通道
paint.colorFilter = const ColorFilter.srgbToLinearGamma();
// 構造一個通過 5x5 矩陣轉換顏色的濾色器,其中第五行隱式添加到標識配置中。
// 每個像素的顏色值,表示為<code>R, G, B, A</code> ,乘以矩陣以創建新顏色:
// | R' | | a00 a01 a02 a03 a04 | | R |
// | G' | | a10 a11 a22 a33 a44 | | G |
// | B' | = | a20 a21 a22 a33 a44 | * | B |
// | A' | | a30 a31 a22 a33 a44 | | A |
// | 1 | | 0 0 0 0 1 | | 1 |
// 矩陣按行優先順序排列,轉換列在未歸一化的 0...255 空間中指定。
paint.colorFilter = const ColorFilter.matrix([
1, 0, 0, 0, 0,
0, 1, 0, 0, 0,
0, 0, 1, 0, 0,
0, 0, 0, 1, 0,
]);
// 創建一個顏色過濾器,應用作為第二個參數給出的混合模式
// 源顏色是作為第一個參數給出的顏色,目標顏色是來自正在合成的圖層的顏色
paint.colorFilter = const ColorFilter.mode(Colors.blue, BlendMode.colorBurn);
invertColors
invertColors → bool?, 繪制時圖像的顏色是否反轉。 反轉圖像的顏色會應用一個新的濾色器,該濾色器將與任何用戶提供的濾色器組成。
paint.invertColors = true;
isAntiAlias
isAntiAlias → bool?,是否對畫布上繪制的線條和圖像應用抗鋸齒,使用了抗鋸齒邊緣更平滑。
// 默認值為true
paint.isAntiAlias = true;
strokeCap
strokeCap → StrokeCap?,當style設置為PaintingStyle.stroke時放置在畫線末端的飾面
// 以平坦邊緣開始和結束輪廓,沒有延伸
paint.strokeCap = StrokeCap.butt;
// 以半圓形延伸開始和結束輪廓
paint.strokeCap = StrokeCap.round;
// 以半方形擴展開始和結束輪廓。這類似於將每個輪廓擴展一半筆畫寬度(由Paint.strokeWidth繪制)
paint.strokeCap = StrokeCap.square;
strokeJoin
strokeJoin → StrokeJoin?,放置在段之間的連接處的那種飾面,只適用於繪制路徑(即PaintingStyle.stroke)。
// 線段之間的連接將線段對接端的角連接起來,以提供斜切外觀
paint.strokeJoin = StrokeJoin.bevel;
// 線段之間的連接形成尖角
paint.strokeJoin = StrokeJoin.miter;
// 線段之間的連接是半圓形的
paint.strokeJoin = StrokeJoin.round;
strokeMiterLimit
strokeMiterLimit → double?,當連接設置為StrokeJoin.miter且style設置為PaintingStyle.stroke時,在線段上繪制斜接的限制。如果超出此限制,則會改為繪制StrokeJoin.bevel連接。
關於strokeMiterLimit是什么可以查看以下文章:
// 默認為4.0
paint.strokeWidth = 20;
strokeWidth
strokeWidth → double?,當style設置為PaintingStyle.stroke時繪制邊緣的寬度。
// 默認值為0.0
paint.strokeWidth = 20;
shader
shader → Shader?,用來描邊或填充形狀時使用的着色器。當它為空時,將使用color。
shader屬性傳遞的值為 Gradient 或 ImageShader對象。
關於shader的使用方法可以查看以下文章:
blendMode
blendMode → BlendMode?,在畫布上繪畫時使用的算法。在畫布上繪制形狀或圖像時,可以使用不同的算法來混合像素。
關於BlendMode的相關資料可以查看以下文章:
filterQuality
filterQuality → FilterQuality?
用於對圖像進行采樣的ImageFilter和Shader對象中的圖像采樣以及用於渲染圖像的Canvas操作的質量級別。
當按比例放大時,質量通常是最低的, low和medium的質量none ,而對於非常大的比例因子(超過 10 倍),質量最高的是high 。
縮小時, medium提供最佳質量,尤其是在將圖像縮小到小於其大小的一半或在此類縮小之間為比例因子設置動畫時。否則, low和high在 50% 和 100% 之間的減少提供類似的效果,但圖像可能會丟失細節並具有低於 50% 的丟失。
為了在放大和縮小圖像或比例未知時獲得高質量, medium通常是一個很好的平衡選擇。
paint.filterQuality = FilterQuality.none;
paint.filterQuality = FilterQuality.low;
paint.filterQuality = FilterQuality.medium;
paint.filterQuality = FilterQuality.high;
imageFilter
imageFilter → ImageFilter?
設置繪制圖片時的圖像過濾器。imageFilter 一共有3個值用來設置:
ImageFilter.blur
用來設置圖片高斯模糊顯示效果,可以傳入3個參數:
double sigmaX
:創建 x 軸的高斯模糊度double sigmaY
:創建 y 軸的高斯模糊度TileMode tileMode
:這個enum用於定義漸變或圖像過濾器應該如何處理定義的內部區域之外的區域
paint.imageFilter = ui.ImageFilter.blur(sigmaX: 50, sigmaY: 50, tileMode: TileMode.clamp);
仔細查看圖片的邊緣,會有不同的效果。
ImageFilter.matrix
用來設置圖片變形狀。
該屬性的用法繁多並且復雜,以后有時間再慢慢研究。要想使用簡單的方法實現變形效果,只要在方法后面加上storage即可:
paint.imageFilter = ui.ImageFilter.matrix(Matrix4.skew(.2, .4).storage);
ImageFilter.compose
用來組合實現圖片高斯模糊和變形。
ui.ImageFilter outer = ui.ImageFilter.blur(sigmaX: 50, sigmaY: 50, tileMode: TileMode.decal);
ui.ImageFilter inner = ui.ImageFilter.matrix(Matrix4.skew(.2, .4).storage);
paint.imageFilter = ui.ImageFilter.compose(outer: outer, inner: inner);
maskFilter
蒙版過濾器(例如,模糊),用於在繪制后但在將其合成到圖像之前應用於形狀。需要傳入2個參數:
BlurStyle _style
:MaskFilter對象中用於模糊的樣式double _sigma
:控制效果的大小。它是要應用的高斯模糊的標准偏差。該值必須大於零。 sigma 大致對應於效果半徑的一半(以像素為單位)
paint.maskFilter = MaskFilter.blur(_style, _sigma);