“This is the fourth day of my participation in the August More Text Challenge. For details, see: August More Text Challenge juejin.cn/post/698796…

The desired effect of the side dish is multiple waves, gradient color, wave width and height customization, etc.

1. Distinguish wave width animations

In the previous section, the wave width was smaller than the screen width. When the wave width was enlarged, the animation would jump a little during the cycle, which was not smooth. The reason for this is thatAnimationThere is a problem with the animation Settings.

The side dish adjusts the Offset position of the pan animation and sets the Offset of the starting position of the wave to the opposite of the small wave;

Return transform.translate (offset: offset (waveWidth * _curvedAnimation.value, 0.0), child: Container(); / / the wavesCopy the code

2. Fill with wave color

Before this, the dishes were all line waves, and the ideal effect of the dishes was filled, so set the last point of the three screens of waves and the first point of the three screens of waves, and connect them by lineTo, and set Paint as the fill effect.

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. The 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. The lineTo (- + plusWidth startOffset, 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; }Copy the code

3. Wave gradient

Once the dish is filled with wave color, to further create a wave gradient, use the Paint brush to set the shader gradient. The starting point of linear gradient starts from the peak to the bottom;

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) color.shader = LinearGradient(begin: Alignment.bottomCenter, end: Alignment.topCenter, colors: [Colors. Blue. WithOpacity (0.4), Colors, white, withOpacity (0.4)]) createShader (the rect);Copy the code

Cut the waves

The wave height of the side dish setting is filled with the parent control by default, but if the height of the parent control is less than the peak to trough height of the wave, the trough is still drawn, at this time the side dish through cutting, only show the maximum height of the setting can be; At this point, pay attention to set the clipping range first, and then the wave drawing;

canvas.save();

canvas.clipPath(_clipPath(size, _plusWidth));
canvas.drawPath(_wavePath(size, _plusWidth), paint);

canvas.restore();
Copy the code

5. Set multiple waves

The small dish wants to show multiple waves at once, so each custom parameter type and Animation are put in the List, and only need to pass multiple data during initialization. These include the wave width and height, the duration of a wave, the initial longitudinal and transverse offset, and the gradient wave color.

// Final double allHeight; <double> waveWidthList final List<double> waveWidthList; // List final List<double> waveHeightList; List final List<double> startOffsetXList; List final List<double> startOffsetYList; // Final List<Duration> durationList; <List<Color>> waveColorList; ACEWave(this.waveWidthList, this.waveHeightList, this.allHeight, {this.durationList, this.startOffsetXList, this.startOffsetYList, this.waveColorList});Copy the code
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 = [color.green. WithOpacity (0.2), color.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, ))));Copy the code


ACEWave case source code


So far, the dish custom wave effect is basically completed, which for performance and exception processing is also perfect; If there is any mistake, please give guidance!

Source: Young Monk Atze