目录
一、效果展示
二、CustomPaint
三、CustomPainter
四、水波效果
五、文字效果
六、动起来
一、效果展示
二、CustomPaint
WaterWave继承CustomPainter用画笔画出来的水波动画效果需要CustomPaint呈现出来。
CustomPaint有两个参数painter和size,painter是一个继承了CustomPainter的对象,主要实现了绘画控件的功能。size指定了控件的大小,如果CustomPaint的child不为空,size的值就是child控件的大小,指定size的值则无效;如果child为空,所指定的size的值,就是画布的大小。
CustomPaint(
painter: WaterWave(this.variable, 0.79, this.offsetX),
size: Size(160, 160),
)
三、CustomPainter
WaterWave继承了CustomPainter,实现了其中两个重要方法:paint和shouldRepaint。paint当自定义控件需要重画时被调用。shouldRepaint则决定当条件变化时是否需要重画。
class WaterWave extends CustomPainter {
@override
void paint(Canvas canvas, Size size) {
}
@override
bool shouldRepaint(ClockPainter oldDelegate) {
return true;
}
}
四、水波效果
绘出水波效果有几个重要的参数:波纹振幅:double waveAmplitude;
波纹周期:double waveCycle;波纹上升速度:double waveGrowth;
波浪x位移:double offsetX;当前波浪上市高度Y(高度从大到小 坐标系向下增长):double currentWavePointY; 模拟波纹:double variable;这几个参数在sin函数和cos函数地计算下模拟出水波的形状,然后画出来。
void firstWave() {
Path path = new Path();
double y = this.currentWavePointY;
path.moveTo(0, y);
for (double x = 0.0; x <= this.waterWaveWidth; x++) {
y = this.waveAmplitude * sin(this.waveCycle * x + this.offsetX) +
this.currentWavePointY;
path.lineTo(x, y);
}
path.lineTo(this.waterWaveWidth, this.size.height);
path.lineTo(0, this.size.height);
path.close();
var paint = new Paint()
..color = Color.fromRGBO(223, 83, 64, 1)
..style = PaintingStyle.fill
..maskFilter = MaskFilter.blur(BlurStyle.inner, 5.0);
this.canvas.drawPath(path, paint);
}
void secondWave() {
Path path = new Path();
double y = this.currentWavePointY;
path.moveTo(0, y);
for (double x = 0.0; x <= this.waterWaveWidth; x++) {
y = this.waveAmplitude * cos(this.waveCycle * x + this.offsetX) +
this.currentWavePointY;
path.lineTo(x, y);
}
path.lineTo(this.waterWaveWidth, this.size.height);
path.lineTo(0, this.size.height);
path.close();
var paint = new Paint()
..color = Color.fromRGBO(236, 90, 66, 1)
..style = PaintingStyle.fill
..maskFilter = MaskFilter.blur(BlurStyle.inner, 5.0);
this.canvas.drawPath(path, paint);
}
五、文字效果
绘画文字的时候需要添加引用,import 'dart:ui' as UI;
UI.ParagraphBuilder pb = UI.ParagraphBuilder(UI.ParagraphStyle(
textAlign: TextAlign.center,
fontWeight: FontWeight.w500,
fontStyle: FontStyle.normal,
fontSize: 70.0,
));
pb.pushStyle(UI.TextStyle(color: Colors.white));
pb.addText('86');
UI.Paragraph paragraph = pb.build();
paragraph.layout(UI.ParagraphConstraints(width: 140));
Offset offset = Offset(10, 30.0);
this.canvas.drawParagraph(paragraph, offset);
UI.ParagraphBuilder pb2 = UI.ParagraphBuilder(UI.ParagraphStyle(
textAlign: TextAlign.center,
fontWeight: FontWeight.w500,
fontStyle: FontStyle.normal,
fontSize: 18.0,
));
pb2.pushStyle(UI.TextStyle(color: Colors.white));
pb2.addText('评分');
UI.Paragraph paragraph2 = pb2.build();
paragraph2.layout(UI.ParagraphConstraints(width: 100));
Offset offset2 = Offset(30, 105.0);
this.canvas.drawParagraph(paragraph2, offset2);
六、动起来
重新initState方法,添加一个定时器没25毫秒改变一下水波的波纹。
variable模拟波纹上下浮动的效果,offsetX模拟波浪的位移,从而能够增强波纹震动的效果。
@override
void initState() {
super.initState();
this.variable = widget.variable;
this.increase = widget.increase;
this.waveSpeed = 0.4 / pi;
this.offsetX = 0.0;
this.timer = Timer.periodic(new Duration(milliseconds: 25), (timer) {
setState(() {
this.offsetX += this.waveSpeed;
if (this.increase) {
this.variable += 0.01;
} else {
this.variable -= 0.01;
}
if (this.variable <= 1) {
this.increase = true;
}
if (this.variable >= 1.6) {
this.increase = false;
}
});
});
}