整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

波浪纹的交互,css的animation

波浪纹的交互,css的animation


//html code
<div class="ripple" title="谢谢点赞~~">
   <span>2021</span>
</div>

样式

缺少@types/node模块所致。该模块用于提供Node.js类型定义的模块,使开发者在编写Node.js代码时获得更好的代码补全和类型检查支持。

解决方案1

开启Node.js编码协助

如果报错无法下载 @types/node No @types/node versions available,可用方案2或3。

解决方案2

全局安装 @types/node 包:

npm install @types/node -g

在 Windows 系统中,全局安装的 node_modules 目录路径通常位于 C:\Users\{用户名}\AppData\Roaming\npm\node_modules。

在Webstorm点击设置,选择语言和框架->JavaScript->库,指定文件夹为C:\Users\Administrator\AppData\Roaming\npm\node_modules\@types。

解决方案3

在项目中局部安装@types/node模块:

npm install @types/node --save-dev

迎去浏览原文:http://tryenough.com/flutter-wave

效果



你可以先简单理解下贝塞尔曲线的原理:

推荐这个关于贝塞尔的教程:http://www.html-js.com/article/1628

代码:

1.创建绘制波浪边界的代码

创建一个基础的绘制类,可接收动画的x和y值:

import 'package:flutter/material.dart';
abstract class BasePainter extends CustomPainter{
 Animation<double> _xAnimation;
 Animation<double> _yAnimation;
 set XAnimation(Animation<double> value) {
 _xAnimation=value;
 }
 set YAnimation(Animation<double> value) {
 _yAnimation=value;
 }
 Animation<double> get YAnimation=> _yAnimation;
 Animation<double> get XAnimation=> _xAnimation;
}

实现

欢迎去浏览原文:http://tryenough.com/flutter-wave

import 'dart:math';
import 'package:flutter_wave/painter_base.dart';
import 'package:flutter/material.dart';
class WavePainter extends BasePainter {
 int waveCount;
 int crestCount;
 double waveHeight;
 List<Color> waveColors;
 double circleWidth;
 Color circleColor;
 Color circleBackgroundColor;
 bool showProgressText;
 TextStyle textStyle;
 WavePainter(
 {this.waveCount=1,
 this.crestCount=2,
 this.waveHeight,
 this.waveColors,
 this.circleColor=Colors.grey,
 this.circleBackgroundColor=Colors.white,
 this.circleWidth=5.0,
 this.showProgressText=true,
 this.textStyle=const TextStyle(
 fontSize: 60.0,
 color: Colors.blue,
 fontWeight: FontWeight.bold,
 shadows: [
 Shadow(color: Colors.grey, offset: Offset(5.0, 5.0), blurRadius: 5.0)
 ],
 )});
 @override
 void paint(Canvas canvas, Size size) {
 double width=size.width;
 double height=size.height;
 if (waveHeight==null) {
 waveHeight=height / 10;
 height=height + waveHeight;
 }
 if (waveColors==null) {
 waveColors=[
 Color.fromARGB(
 100, Colors.blue.red, Colors.blue.green, Colors.blue.blue)
 ];
 }
 Offset center=new Offset(width / 2, height / 2);
 double xMove=width * XAnimation.value;
 double yAnimValue=0.0;
 if (YAnimation !=null) {
 yAnimValue=YAnimation.value;
 }
 double yMove=height * (1.0 - yAnimValue);
 Offset waveCenter=new Offset(xMove, yMove);
 var paintCircle=new Paint()
 ..color=Colors.grey
 ..style=PaintingStyle.fill
 ..strokeWidth=circleWidth
 ..maskFilter=MaskFilter.blur(BlurStyle.inner, 5.0);
// canvas.drawCircle(center, min(width, height) / 2, paintCircle);
 List<Path> wavePaths=[];
 for (int index=0; index < waveCount; index++) {
 double direction=pow(-1.0, index);
 Path path=new Path()
 ..moveTo(waveCenter.dx - width, waveCenter.dy)
 ..lineTo(waveCenter.dx - width, center.dy + height / 2)
 ..lineTo(waveCenter.dx + width, center.dy + height / 2)
 ..lineTo(waveCenter.dx + width, waveCenter.dy);
 for (int i=0; i < 2; i++) {
 for (int j=0; j < crestCount; j++) {
 double a=pow(-1.0, j);
 path
 ..quadraticBezierTo(
 waveCenter.dx +
 width * (1 - i - (1 + 2 * j) / (2 * crestCount)),
 waveCenter.dy + waveHeight * a * direction,
 waveCenter.dx +
 width * (1 - i - (2 + 2 * j) / (2 * crestCount)),
 waveCenter.dy);
 }
 }
 path..close();
 wavePaths.add(path);
 }
 var paint=new Paint()
 ..color=circleBackgroundColor
 ..style=PaintingStyle.fill
 ..maskFilter=MaskFilter.blur(BlurStyle.inner, 5.0);
 canvas.saveLayer(
 Rect.fromCircle(center: center, radius: min(width, height) / 2), paint);
// canvas.drawCircle(center, min(width, height) / 2, paint);
 paint
// ..blendMode=BlendMode.srcATop
 ..style=PaintingStyle.fill
 ..strokeWidth=2.0
 ..maskFilter=MaskFilter.blur(BlurStyle.inner, 10.0);
 for (int i=0; i < wavePaths.length; i++) {
 if (waveColors.length >=wavePaths.length) {
 paint.color=waveColors[i];
 } else {
 paint.color=waveColors[0];
 }
 canvas.drawPath(wavePaths[i], paint);
 }
// paint.blendMode=BlendMode.srcATop;
 if (showProgressText) {
 TextPainter tp=TextPainter(
 text: TextSpan(
 text: '${(yAnimValue * 100.0).toStringAsFixed(0)}%',
 style: textStyle),
 textDirection: TextDirection.rtl)
 ..layout();
 tp.paint(
 canvas, Offset(center.dx - tp.width / 2, center.dy - tp.height / 2));
 }
 canvas.restore();
 }
 @override
 bool shouldRepaint(CustomPainter oldDelegate) {
 return oldDelegate !=this;
 }
}

欢迎去浏览原文:http://tryenough.com/flutter-wave

2.创建工厂方法,用于创建波浪图形

import 'package:flutter/material.dart';

import 'package:flutter_wave/painter_base.dart';

import 'package:flutter_wave/painter/painter_wave.dart';

abstract class BasePainterFactory {

BasePainter getPainter();

}

class WavePainterFactory extends BasePainterFactory {

BasePainter getPainter() {

return WavePainter(

waveCount: 1,

waveColors: [

Colors.lightBlueAccent[200],

],

textStyle:

TextStyle(

fontSize: 60.0,

foreground: Paint()

..color=Colors.lightBlue

..style=PaintingStyle.fill

..strokeWidth=2.0

..blendMode=BlendMode.difference

..colorFilter=ColorFilter.mode(Colors.white, BlendMode.exclusion)

..maskFilter=MaskFilter.blur(BlurStyle.solid, 1.0),

fontWeight: FontWeight.bold,

),

);

}

}

给波浪添加动画

推荐你先学一下动画基础知识:

https://juejin.im/post/5b6270edf265da0f473539a6

原理解释:

xAnimation和yAnimation不断的从0到1变化,然后上面绘制波浪的地方根据这些值不断的进行绘制,形成动画。

import 'package:flutter_wave/painter_factory.dart';
import 'package:flutter/material.dart';
class ProgressManager extends StatefulWidget {
 @override
 _ProgressManagerState createState()=>
 new _ProgressManagerState().._factory=WavePainterFactory();
}
class _ProgressManagerState extends State<ProgressManager>
 with TickerProviderStateMixin {
 AnimationController xController;
 AnimationController yController;
 Animation<double> xAnimation;
 Animation<double> yAnimation;
 List<double> _progressList=[];
 double curProgress=0;
 BasePainterFactory _factory;
 set painter(BasePainterFactory factory) {
 _factory=factory;
 }
 setProgress(double progress) {
 _progressList.add(progress);
 onProgressChange();
 }
 onProgressChange() {
 if (_progressList.length > 0) {
 if (yController !=null && yController.isAnimating) {
 return;
 }
 double nextProgress=_progressList[0];
 _progressList.removeAt(0);
 final double begin=curProgress;
 yController=new AnimationController(
 vsync: this, duration: Duration(milliseconds: 1000));
 yAnimation=new Tween(begin: begin, end: nextProgress).animate(yController);
 yAnimation.addListener(_onProgressChange);
 yAnimation.addStatusListener(_onProgressStatusChange);
 yController.forward();
 }
 }
 @override
 void initState() {
 super.initState();
 xController=new AnimationController(
 vsync: this, duration: Duration(milliseconds: 4000));
 xAnimation=new Tween(begin: 0.0, end: 1.0).animate(xController);
 xAnimation.addListener(_change);
 yController=new AnimationController(
 vsync: this, duration: Duration(milliseconds: 5000));
 yAnimation=new Tween(begin: 0.0, end: 1.0).animate(yController);
 yAnimation.addListener(_onProgressChange);
 yAnimation.addStatusListener(_onProgressStatusChange);
 doDelay(xController, 0);
 Future.delayed(Duration(milliseconds: 3000), () {
 setProgress(0.66);
 });
 }
 @override
 Widget build(BuildContext context) {
 return Center(
 child:
 Container(
 width: MediaQuery.of(context).size.width,
 height: 400.0,
 child: new CustomPaint(
 painter: _factory.getPainter()
 ..XAnimation=xAnimation
 ..YAnimation=yAnimation,
 size: new Size(MediaQuery.of(context).size.width, 400.0),
 ),
 ),
 );
 }
 void _change() {
 setState(() {});
 }
 void _onProgressChange() {
 setState(() {
 curProgress=yAnimation.value;
 });
 }
 void _onProgressStatusChange(status) {
 if (status==AnimationStatus.completed) {
 onProgressChange();
 }
 }
 void doDelay(AnimationController controller, int delay) async {
 Future.delayed(Duration(milliseconds: delay), () {
 controller..repeat();
 });
 }
 @override
 void dispose() {
 xController.dispose();
 yController.dispose();
 xAnimation.removeListener(_change);
 yAnimation.removeListener(_onProgressChange);
 yAnimation.removeStatusListener(_onProgressStatusChange);
 super.dispose();
 }
}

使用的地方

body: Center(
 child: Column(
 mainAxisAlignment: MainAxisAlignment.center,
 children: <Widget>[
 ProgressManager(),
 ],
 ),
 ),

欢迎去浏览原文:http://tryenough.com/flutter-wave

下载demo地址

http://tryenough.com/flutter-wave