和尚继续完善前两天自定义 ACEWave 波浪组件,和尚预期的效果是多条波浪,渐变颜色,波浪宽高自定义等;
和尚上一节测试时波浪宽度小于屏幕宽度,当放大波浪宽度时,循环过程中动画会跳动一下,不顺畅;其原因是 Animation 动画设置有问题;
和尚调整了平移动画的 Offset 位置,并设置波浪起始位置偏移量与小波浪时相反;
return Transform.translate( offset: Offset(waveWidth * _curvedAnimation.value, 0.0), child: Container(); // 波浪
再此之前和尚尝试的均为线条波浪,和尚理想的效果的是有填充色的,于是设置三屏波浪最末点与三屏波浪的最初点,通过 lineTo 连接起来,并设置 Paint 画笔为填充效果;
Path _wavePath(path, size, plusWidth) { for (int i = 0; i < _count; i++) { path.moveTo(waveWidth * i - size.width - startOffset, startOffsetY); path.quadraticBezierTo( _quaterWidth + waveWidth * i - size.width - startOffset, startOffsetY - waveHeight, _quaterWidth * 2 + waveWidth * i - size.width - startOffset, startOffsetY); path.moveTo(_quaterWidth * 2 + waveWidth * i - size.width - startOffset, startOffsetY); path.quadraticBezierTo( _quaterWidth * 3 + waveWidth * i - size.width - startOffset, startOffsetY + waveHeight, _quaterWidth * 4 + waveWidth * i - size.width - startOffset, startOffsetY); path.moveTo(_quaterWidth * 4 + waveWidth * i - size.width - startOffset, startOffsetY); } path.lineTo(_quaterWidth * 4 + waveWidth * (_count - 1) - size.width - startOffset, 600.0); path.lineTo(-size.width - startOffset, 600.0); path.lineTo(-size.width - startOffset, startOffsetY); for (int i = 0; i < _count; i++) { path.moveTo(waveWidth * i - startOffset + plusWidth, startOffsetY); path.quadraticBezierTo( _quaterWidth + waveWidth * i - startOffset + plusWidth, startOffsetY - waveHeight, _quaterWidth * 2 + waveWidth * i - startOffset + plusWidth, startOffsetY); path.moveTo(_quaterWidth * 2 + waveWidth * i - startOffset + plusWidth, startOffsetY); path.quadraticBezierTo( _quaterWidth * 3 + waveWidth * i - startOffset + plusWidth, startOffsetY + waveHeight, _quaterWidth * 4 + waveWidth * i - startOffset + plusWidth, startOffsetY); path.moveTo(_quaterWidth * 4 + waveWidth * i - startOffset + plusWidth, startOffsetY); } path.lineTo(_quaterWidth * 4 + waveWidth * (_count - 1) - startOffset + plusWidth, 600.0); path.lineTo(-startOffset + plusWidth, 600.0); path.lineTo(-startOffset + plusWidth, startOffsetY); for (int i = 0; i < _count; i++) { path.moveTo(waveWidth * i + size.width - startOffset + plusWidth * 2, startOffsetY); path.quadraticBezierTo( _quaterWidth + waveWidth * i + size.width - startOffset + plusWidth * 2, startOffsetY - waveHeight, _quaterWidth * 2 + waveWidth * i + size.width - startOffset + plusWidth * 2, startOffsetY); path.moveTo( _quaterWidth * 2 + waveWidth * i + size.width - startOffset + plusWidth * 2, startOffsetY); path.quadraticBezierTo( _quaterWidth * 3 + waveWidth * i + size.width - startOffset + plusWidth * 2, startOffsetY + waveHeight, _quaterWidth * 4 + waveWidth * i + size.width - startOffset + plusWidth * 2, startOffsetY); path.moveTo(_quaterWidth * 4 + waveWidth * i + size.width - startOffset + plusWidth * 2, startOffsetY); } path.lineTo( _quaterWidth * 4 + waveWidth * (_count - 1) + size.width - startOffset + plusWidth * 2, 600.0); path.lineTo(size.width - startOffset + plusWidth * 2, 600.0); path.lineTo(size.width - startOffset + plusWidth * 2, startOffsetY); return path; }
和尚填充完波浪颜色之后,想进一步实现波浪渐变色,可以通过 Paint 画笔来设置 shader 渐变效果;其中线性渐变的起始点从波峰开始,至最底部为止;
Paint paint = Paint() ..color = Colors.blue ..strokeCap = StrokeCap.round ..strokeWidth = 6 ..style = PaintingStyle.fill; var rect = Offset(0.0, startOffsetY) & Size(size.width, size.height) paint.shader = LinearGradient( begin: Alignment.bottomCenter, end: Alignment.topCenter, colors: [Colors.blue.withOpacity(0.4), Colors.white.withOpacity(0.4) ]).createShader(rect);
和尚设置的波浪高度默认是填充满父控件的,但若父控件高度小于波浪的波峰到波谷高度时,波谷依然绘制出来,此时和尚通过裁剪方式,只展示设置的最高高度即可;此时注意优先设置裁剪范围,之后再进行波浪的绘制;
canvas.save(); canvas.clipPath(_clipPath(size, _plusWidth)); canvas.drawPath(_wavePath(size, _plusWidth), paint); canvas.restore();
和尚想一次性展示多条波浪,于是将各个自定义参数类型及动画 Animation 放在 List 中,只需在初始化时传递多条数据即可;其中包括波浪宽高,一个波浪动画时长,初始横纵偏移量以及渐变色波浪颜色等;
// 波浪整体高度(裁剪后) final double allHeight; // 一个周期波浪宽度 List final List<double> waveWidthList; // 波峰到中心点高度 List final List<double> waveHeightList; // 水平偏移量 List final List<double> startOffsetXList; // 波峰距顶点偏移量 List final List<double> startOffsetYList; // 时间 List final List<Duration> durationList; // 渐变色 List final List<List<Color>> waveColorList; ACEWave(this.waveWidthList, this.waveHeightList, this.allHeight, {this.durationList, this.startOffsetXList, this.startOffsetYList, this.waveColorList});
List<double> waveWidth = [600, 800, 300]; List<double> waveHeight = [60, 80, 70]; List<double> startOffsetX = [30, 150, 100]; List<double> startOffsetY = [100, 120, 100]; List<Duration> duration = [ Duration(milliseconds: 6000), Duration(milliseconds: 4000), Duration(milliseconds: 5000) ]; List<List<Color>> colorList = [ [Colors.green.withOpacity(0.2), Colors.white.withOpacity(0.4)], [Colors.blue.withOpacity(0.2), Colors.white.withOpacity(0.4)], [Colors.blue.withOpacity(0.2), Colors.white.withOpacity(0.4)] ]; return Scaffold( appBar: AppBar(title: Text('ACEWave Page')), body: Container( color: Colors.grey, height: (MediaQuery.of(context).size.height), child: Container( child: ACEWave( waveWidth, waveHeight, 300.0, startOffsetXList: startOffsetX, startOffsetYList: startOffsetY, durationList: duration, waveColorList: colorList, ))));
ACEWave 案例源码
本文分享自微信公众号 - 阿策小和尚(gh_8297e718c166),作者:阿策小和尚
原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。
原始发表时间:2020-04-19
本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。
我来说两句