是什麼
Paint有個屬性叫shader,也就是著色器,用於:
- 畫 或 填充一個圖形時增加特殊效果,如drawCircle時,新增顏色漸變效果。
- 優先順序:colorFilter > shader > color,當共同存在時,優先順序高的生效,優先順序低的無效。
- Gradient,繪製顏色漸變的著色器。
- ImageShader,對圖片做處理的著色器。
直白來講,shader就是設定一個紋理圖案,然後貼到要畫的內容上。
Gradient
- linear,線性漸變
- radial,徑向漸變,指的是圓圈,由內而外
- sweep,掃描漸變,雷達掃描效果
linear
建構函式:
Gradient.linear(
Offset from,
Offset to,
List<Color> colors, [
List<double>? colorStops,
TileMode tileMode = TileMode.clamp,
Float64List? matrix4,
])
複製程式碼
- from,to, 確定Gradient影響的範圍。
- colors,指定線性漸變的顏色值陣列.colors 與 colorStops的長度要相同。
- colorStops,陣列中每個值是0.0-1.0之間。colorStops[i]確定colors[i]從哪兒開始,指的是從from to中哪兒開始。
- TileMode,colors的渲染模式。針對的是超出from to後怎麼處理。
- clamp,超出from to邊界後用最近的顏色渲染,直到最後。如果不顯示設定,此是預設值。
- repeated,超出from to邊界後重復
- mirror, 超出from to邊界後映象顯示
TileMode.clamp
void _testGradientLinear(Canvas canvas, Size size) {
Paint _paint = Paint();
_paint.isAntiAlias = true;
_paint.style = PaintingStyle.stroke;
_paint.strokeWidth = 30;
_paint.shader = ui.Gradient.linear(
Offset(-150, 0),
Offset(100, 0),
[Colors.red, Colors.blue, Colors.green],
[0.2, 0.4, 0.6],
TileMode.clamp,
Float64List.fromList([
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1,
])
// TileMode.repeated,
// TileMode.mirror
);
canvas.drawLine(Offset(-150, 0), Offset(200, 0), _paint);
}
複製程式碼
TileMode.repeated
效果一直重複往前疊加
void _testGradientLinear(Canvas canvas, Size size) {
Paint _paint = Paint();
_paint.isAntiAlias = true;
_paint.style = PaintingStyle.stroke;
_paint.strokeWidth = 30;
_paint.shader = ui.Gradient.linear(
Offset(-100, 0),
Offset(100, 0),
[Colors.red, Colors.blue, Colors.green],
[0.2, 0.4, 0.6],
// TileMode.clamp,
TileMode.repeated,
// TileMode.mirror,
Float64List.fromList([
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1,
]),
//
);
canvas.drawLine(Offset(-150, 0), Offset(150, 0), _paint);
}
複製程式碼
TileMode.mirror
void _testGradientLinear(Canvas canvas, Size size) {
Paint _paint = Paint();
_paint.isAntiAlias = true;
_paint.style = PaintingStyle.stroke;
_paint.strokeWidth = 30;
_paint.shader = ui.Gradient.linear(
Offset(-100, 0),
Offset(100, 0),
[Colors.red, Colors.blue, Colors.green],
[0.2, 0.4, 0.6],
// TileMode.clamp,
// TileMode.repeated,
TileMode.mirror,
Float64List.fromList([
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1,
]),
);
canvas.drawLine(Offset(-150, 0), Offset(150, 0), _paint);
}
複製程式碼
radial
建構函式:
Gradient.radial(
Offset center,
double radius,
List<Color> colors, [
List<double>? colorStops,
TileMode tileMode = TileMode.clamp,
Float64List? matrix4,
Offset? focal,
double focalRadius = 0.0
])
複製程式碼
- center 中心點
- radius 半徑,類似於linear的from to
- colors,指定線性漸變的顏色值陣列.colors 與 colorStops的長度要相同。
- colorStops,陣列中每個值是0.0-1.0之間。colorStops[i]確定colors[i]從哪兒開始,指的是從center 到 radius中哪兒開始。
- TileMode,colors的渲染模式。針對的是超出radius後怎麼處理。
- clamp,超出radius邊界後用最近的顏色渲染,直到最後。如果不顯示設定,此是預設值。
- repeated,超出radius邊界後重復
- mirror, 超出radius邊界後映象顯示
- focal 設定shader圓心的偏移量,該圓心向focal的xy方向擠壓效果
- focalRadius 半徑
下面這個例子,是畫了一條線,然後設定上shader:
void _testGradientRadial(Canvas canvas, Size size) {
Paint _paint = Paint();
_paint.isAntiAlias = true;
_paint.style = PaintingStyle.stroke;
_paint.strokeWidth = 200;
_paint.shader = ui.Gradient.radial(
Offset(0, 0),
150,
[Colors.red, Colors.blue, Colors.green],
[0.2, 0.4, 0.6],
TileMode.clamp,
// TileMode.repeated,
// TileMode.mirror,
Float64List.fromList([
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1,
]),
);
canvas.drawLine(Offset(-100, 0), Offset(100, 0), _paint);
}
複製程式碼
TileMode.clamp
void _testGradientRadial(Canvas canvas, Size size) {
Paint _paint = Paint();
_paint.isAntiAlias = true;
_paint.style = PaintingStyle.fill;
_paint.strokeWidth = 1;
_paint.shader = ui.Gradient.radial(
Offset(-80, -100),
100,
[Colors.red, Colors.blue, Colors.green],
[0.2, 0.4, 0.8],
TileMode.clamp,
// TileMode.repeated,
// TileMode.mirror,
);
canvas.drawCircle(Offset(-80, -100), 70, _paint);
_paint.shader = ui.Gradient.radial(
Offset(-80, 100),
100,
[Colors.red, Colors.blue, Colors.green],
[0.2, 0.4, 0.8],
TileMode.clamp,
// TileMode.repeated,
// TileMode.mirror,
);
canvas.drawCircle(Offset(-80, 100), 120, _paint);
}
複製程式碼
void _testGradientRadial(Canvas canvas, Size size) {
Paint _paint = Paint();
_paint.isAntiAlias = true;
_paint.style = PaintingStyle.fill;
_paint.strokeWidth = 1;
_paint.shader = ui.Gradient.radial(
Offset(-60, -100),
100,
[Colors.red, Colors.blue, Colors.green],
[0.2, 0.4, 0.8],
TileMode.clamp,
// TileMode.repeated,
// TileMode.mirror,
);
canvas.drawCircle(Offset(-80, -100), 70, _paint);
_paint.shader = ui.Gradient.radial(
Offset(-80, 100),
100,
[Colors.red, Colors.blue, Colors.green],
[0.2, 0.4, 0.8],
TileMode.clamp,
// TileMode.repeated,
// TileMode.mirror,
);
canvas.drawCircle(Offset(-80, 100), 120, _paint);
}
複製程式碼
TileMode.repeated
超過shader的radius後重復
void _testGradientRadial(Canvas canvas, Size size) {
Paint _paint = Paint();
_paint.isAntiAlias = true;
_paint.style = PaintingStyle.fill;
_paint.strokeWidth = 1;
_paint.shader = ui.Gradient.radial(
Offset(0, 0),
80,
[Colors.red, Colors.blue, Colors.green],
[0.2, 0.4, 0.8],
// TileMode.clamp,
TileMode.repeated,
// TileMode.mirror,
);
canvas.drawCircle(Offset(0, 0), 200, _paint);
}
複製程式碼
TileMode.mirror
超過shader的radius後映象顯示
void _testGradientRadial(Canvas canvas, Size size) {
Paint _paint = Paint();
_paint.isAntiAlias = true;
_paint.style = PaintingStyle.fill;
_paint.strokeWidth = 1;
_paint.shader = ui.Gradient.radial(
Offset(0, 0),
80,
[Colors.red, Colors.blue, Colors.green],
[0.2, 0.4, 0.8],
// TileMode.clamp,
// TileMode.repeated,
TileMode.mirror,
);
canvas.drawCircle(Offset(0, 0), 200, _paint);
}
複製程式碼
focal
focal偏向哪裡就向哪裡擠壓,換個描述就是,從shader的center到focal延長線的擠壓
void _testGradientRadialFocol(Canvas canvas, Size size) {
Paint _paint = Paint();
_paint.isAntiAlias = true;
_paint.style = PaintingStyle.fill;
_paint.strokeWidth = 1;
_paint.shader = ui.Gradient.radial(
Offset(0, 0),
80,
[Colors.red, Colors.blue, Colors.green],
[0.2, 0.4, 0.8],
// TileMode.clamp,
TileMode.repeated,
// TileMode.mirror,
Float64List.fromList([
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1,
]),
Offset(40,1),
5
);
canvas.drawCircle(Offset(0, 0), 200, _paint);
}
複製程式碼
sweep
建構函式:
Gradient.sweep(
Offset center,
List<Color> colors, [
List<double>? colorStops,
TileMode tileMode = TileMode.clamp,
double startAngle = 0.0,
double endAngle = math.pi * 2,
Float64List? matrix4,
])
複製程式碼
- center 圓心
- colors 漸變色
- colorStops colors[i]漸變起點
- tileMode 模式
- startAngle 起始角度,類似於linear的from
- endAngle 結束角度,類似於linear的to, 設定的是漸變範圍
TileMode.clamp
void _testGradientSweep(Canvas canvas, Size size) {
Paint _paint = Paint();
_paint.isAntiAlias = true;
_paint.style = PaintingStyle.fill;
_paint.strokeWidth = 1;
_paint.shader = ui.Gradient.sweep(
Offset(0, 0),
[Colors.red, Colors.blue, Colors.green],
[0.3, 0.5, 1],
TileMode.clamp,
// TileMode.repeated,
// TileMode.mirror,
0,
pi/2
);
canvas.drawCircle(Offset(0, 0), 200, _paint);
}
複製程式碼
TileMode.repeated
void _testGradientSweep(Canvas canvas, Size size) {
Paint _paint = Paint();
_paint.isAntiAlias = true;
_paint.style = PaintingStyle.fill;
_paint.strokeWidth = 1;
_paint.shader = ui.Gradient.sweep(
Offset(0, 0),
[Colors.red, Colors.blue, Colors.green],
[0.3, 0.5, 1],
// TileMode.clamp,
TileMode.repeated,
// TileMode.mirror,
0,
pi/2
);
canvas.drawCircle(Offset(0, 0), 200, _paint);
}
複製程式碼
TileMode.mirror
void _testGradientSweep(Canvas canvas, Size size) {
Paint _paint = Paint();
_paint.isAntiAlias = true;
_paint.style = PaintingStyle.fill;
_paint.strokeWidth = 1;
_paint.shader = ui.Gradient.sweep(
Offset(0, 0),
[Colors.red, Colors.blue, Colors.green],
[0.3, 0.5, 1],
// TileMode.clamp,
// TileMode.repeated,
TileMode.mirror,
0,
pi/2
);
canvas.drawCircle(Offset(0, 0), 200, _paint);
}
複製程式碼
ImageShader
用圖片當做紋理。
建構函式:
ImageShader(Image image, TileMode tmx, TileMode tmy, Float64List matrix4)
複製程式碼
- image 當做紋理的圖片
- tmx 在x方向的渲染方式 TimeMode 效果跟前面一樣,不再細說
- tmy 在y方向的渲染方式
TileMode.clamp
void _testImageShader(Canvas canvas, Size size) {
Paint _paint = Paint();
_paint.isAntiAlias = true;
_paint.shader = ImageShader(_src, TileMode.clamp,
TileMode.clamp,
// TileMode.repeated,
// TileMode.mirror,
Float64List.fromList([
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1,
]));
canvas.drawCircle(Offset.zero, 200, _paint);
}
複製程式碼
TileMode.repeated
void _testImageShader(Canvas canvas, Size size) {
Paint _paint = Paint();
_paint.isAntiAlias = true;
_paint.shader = ImageShader(_src, TileMode.repeated, TileMode.repeated, Float64List.fromList([
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1,
]));
canvas.drawCircle(Offset.zero, 200, _paint);
}
複製程式碼
TileMode.mirror
void _testImageShader(Canvas canvas, Size size) {
Paint _paint = Paint();
_paint.isAntiAlias = true;
_paint.shader = ImageShader(_src, TileMode.mirror,
TileMode.mirror,
// TileMode.repeated,
// TileMode.mirror,
Float64List.fromList([
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1,
]));
canvas.drawCircle(Offset.zero, 200, _paint);
}
複製程式碼