当前位置: 首页 > news >正文

Flutter动画—涟漪效果

功能分析

  • 涟漪是由几个圆重叠在一起的

  • 外层圆环比内层圆环的背景色要淡,可以改变外层圆的透明度

  • 想要达到涟漪效果只要将每个圆的半径慢慢变大并且循环动画即可

​实现方法

  1. 在画板上创建三个圆环,再实现外层的圆环要比内层圆环的颜色要淡。

class WaterRipplePainter extends CustomPainter {final Paint _paint = Paint()..style = PaintingStyle.fill;WaterRipplePainter(  );int count = 3;Color color = const Color(0xFF0080ff);@overridevoid paint(Canvas canvas, Size size) {double radius = min(size.width / 2, size.height / 2);for (int i = count; i >= 0; i--) {final double opacity = (1.0 - ((i) / (count + 1)));final Color _color = color.withOpacity(opacity);_paint..color = _color;double _radius = radius * ((i) / (count + 1));canvas.drawCircle(Offset(size.width / 2, size.height / 2), _radius, _paint);}}@overridebool shouldRepaint(CustomPainter oldDelegate) {return true;}
}
class TextLiany extends StatelessWidget {const TextLiany({super.key});@overrideWidget build(BuildContext context) {return Scaffold(body: Container(width: 500,height: 500,child: CustomPaint(painter: WaterRipplePainter(),),),);}
}

2. 使用动画让圆环动起来

class WaterRipplePainter extends CustomPainter {final double progress;final Paint _paint = Paint()..style = PaintingStyle.fill;WaterRipplePainter(this.progress,);int count = 3;Color color = const Color(0xFF0080ff);@overridevoid paint(Canvas canvas, Size size) {double radius = min(size.width / 2, size.height / 2);for (int i = count; i >= 0; i--) {final double opacity = (1.0 - ((i) / (count + 1)));final Color _color = color.withOpacity(opacity);_paint..color = _color;double _radius = radius * ((i + progress) / (count + 1));canvas.drawCircle(Offset(size.width / 2, size.height / 2), _radius, _paint);}}@overridebool shouldRepaint(CustomPainter oldDelegate) {return true;}
}class TextLiany extends StatefulWidget {const TextLiany({super.key});@overrideState<TextLiany> createState() => _TextLianyState();
}class _TextLianyState extends State<TextLiany>with SingleTickerProviderStateMixin {late AnimationController _controller;@overridevoid initState() {super.initState();_controller = AnimationController(vsync: this,duration: const Duration(milliseconds: 2000),)..repeat();}@overridevoid dispose() {_controller.dispose();super.dispose();}@overrideWidget build(BuildContext context) {return Scaffold(body: Center(child: AnimatedBuilder(animation: _controller,builder: (context, child) {return Container(width: 200,height: 200,child: CustomPaint(painter: WaterRipplePainter(_controller.value),),);}),),);}
}

3.使用上面的代码我们发现圆环能够向外扩散了,但是扩散后会出现卡顿的现象,然后重新开始动画。这是因为我们现在只是改变了每个圆的半径,当我们把圆的背景色也跟随半径变大而更加透明后在视觉上就不会出现这种现象了

只需要改变WaterRipplePainter类即可

class WaterRipplePainter extends CustomPainter {final double progress;final Paint _paint = Paint()..style = PaintingStyle.fill;WaterRipplePainter(this.progress,);int count = 3;Color color = const Color(0xFF0080ff);@overridevoid paint(Canvas canvas, Size size) {double radius = min(size.width / 2, size.height / 2);for (int i = count; i >= 0; i--) {final double opacity = (1.0 - ((i + progress) / (count + 1)));final Color _color = color.withOpacity(opacity);_paint..color = _color;double _radius = radius * ((i + progress) / (count + 1));canvas.drawCircle(Offset(size.width / 2, size.height / 2), _radius, _paint);}}@overridebool shouldRepaint(CustomPainter oldDelegate) {return true;}
}

这时候我们的发现不会卡顿了


4.为了后期方便,我们把涟漪个数、涟漪颜色、涟漪动画控制器、涟漪所占宽度等内容全部需要传进来。

完整封装

import 'dart:math';import 'package:flutter/material.dart';class WaterRipple extends StatefulWidget {const WaterRipple({super.key,this.count = 3,this.color = const Color(0xFF0080ff),this.width = 300,this.controller,});final int count; //涟漪的个数final Color color; //涟漪的颜色final double? width; //涟漪的宽高final AnimationController? controller; //涟漪动画控制器@overrideState<WaterRipple> createState() => _WaterRippleState();
}class _WaterRippleState extends State<WaterRipple>with SingleTickerProviderStateMixin {late AnimationController _controller;@overridevoid initState() {_controller = widget.controller != null? widget.controller!: AnimationController(vsync: this,duration: const Duration(milliseconds: 2000),)..repeat();super.initState();}@overridevoid dispose() {_controller.dispose();super.dispose();}@overrideWidget build(BuildContext context) {return SizedBox(width: widget.width,height: widget.width,child: AnimatedBuilder(animation: _controller,builder: (context, child) {return CustomPaint(painter: WaterRipplePainter(_controller.value,count: widget.count,color: widget.color,),);},),);}
}class WaterRipplePainter extends CustomPainter {final double progress;final int count;final Color color;final Paint _paint = Paint()..style = PaintingStyle.fill;WaterRipplePainter(this.progress, {this.count = 3,this.color = const Color(0xFF0080ff),});@overridevoid paint(Canvas canvas, Size size) {double radius = min(size.width / 2, size.height / 2);for (int i = count; i >= 0; i--) {final double opacity = (1.0 - ((i + progress) / (count + 1)));final Color _color = color.withOpacity(opacity);_paint..color = _color;double _radius = radius * ((i + progress) / (count + 1));canvas.drawCircle(Offset(size.width / 2, size.height / 2), _radius, _paint);}}@overridebool shouldRepaint(CustomPainter oldDelegate) {return true;}
}class TextLiany extends StatefulWidget {const TextLiany({super.key});@overrideState<TextLiany> createState() => _TextLianyState();
}class _TextLianyState extends State<TextLiany>with SingleTickerProviderStateMixin {late AnimationController _controller;@overridevoid initState() {super.initState();_controller = AnimationController(vsync: this,duration: const Duration(milliseconds: 2000),)..repeat();}@overridevoid dispose() {_controller.dispose();super.dispose();}@overrideWidget build(BuildContext context) {return const Scaffold(body: WaterRipple(),);}
}

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • arcgis Feature Server的新增、更新、删除
  • 使用 Grype 检查 .jar 包中的漏洞
  • Python 调用手机摄像头
  • Flask 第二课 -- 安装
  • 常见文档工具对比和选择
  • 解锁SQL基础应用新境界:从入门到精通的扩展实践指南(SQL扩展)
  • 1765asp.net古镇旅游网站VS开发sqlserver数据库web结构c#编程web网页设计
  • 华为OD机试真题 - 抢7游戏(Python/JS/C/C++ 2024 D卷 100分)
  • 小琳AI课堂:Nezha模型:基于Transformer的中文预训练语言模型优化与进展
  • ​数据链路层——流量控制可靠传输机制 ​
  • 高职人工智能训练师边缘计算实训室解决方案
  • 【Unity3D】如何用MMD4Mecanim插件将pmx格式模型转换为fbx格式模型
  • jEasyUI 创建带复选框的树形菜单
  • 《高校教育管理》
  • 兔英语语法体系——观后笔记
  • 网络传输文件的问题
  • “寒冬”下的金三银四跳槽季来了,帮你客观分析一下局面
  • create-react-app做的留言板
  • ES6 ...操作符
  • ES6简单总结(搭配简单的讲解和小案例)
  • Git同步原始仓库到Fork仓库中
  • HomeBrew常规使用教程
  • Java编程基础24——递归练习
  • magento2项目上线注意事项
  • Map集合、散列表、红黑树介绍
  • Markdown 语法简单说明
  • php中curl和soap方式请求服务超时问题
  • Spark VS Hadoop:两大大数据分析系统深度解读
  • 开年巨制!千人千面回放技术让你“看到”Flutter用户侧问题
  • 用Canvas画一棵二叉树
  • 第二十章:异步和文件I/O.(二十三)
  • 你学不懂C语言,是因为不懂编写C程序的7个步骤 ...
  • (1)Nginx简介和安装教程
  • (Oracle)SQL优化技巧(一):分页查询
  • (SERIES12)DM性能优化
  • (附源码)spring boot儿童教育管理系统 毕业设计 281442
  • (一)spring cloud微服务分布式云架构 - Spring Cloud简介
  • (一)Thymeleaf用法——Thymeleaf简介
  • (转)创业的注意事项
  • (转)从零实现3D图像引擎:(8)参数化直线与3D平面函数库
  • .NET CORE Aws S3 使用
  • .net core 实现redis分片_基于 Redis 的分布式任务调度框架 earth-frost
  • .NET delegate 委托 、 Event 事件,接口回调
  • .NET 漏洞分析 | 某ERP系统存在SQL注入
  • .NetCore Flurl.Http 升级到4.0后 https 无法建立SSL连接
  • .NET导入Excel数据
  • .vue文件怎么使用_我在项目中是这样配置Vue的
  • @angular/cli项目构建--Dynamic.Form
  • @LoadBalanced 和 @RefreshScope 同时使用,负载均衡失效分析
  • [ C++ ] STL---仿函数与priority_queue
  • [ Socket学习 ] 第一章:网络基础知识
  • [ vulhub漏洞复现篇 ] JBOSS AS 4.x以下反序列化远程代码执行漏洞CVE-2017-7504
  • [28期] lamp兄弟连28期学员手册,请大家务必看一下
  • [android] 天气app布局练习
  • [Android学习笔记]ScrollView的使用