是什么
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);
}