Flutter粒子生成演示

演示:

直接上代码:

import 'dart:math';
import 'dart:ui';import 'package:flutter/material.dart';
import 'package:kq_flutter_widgets/widgets/chart/ex/extension.dart';class ParticleView extends StatefulWidget {const ParticleView({super.key});@overrideState<StatefulWidget> createState() => ParticleViewState();
}class ParticleViewState extends State<ParticleView>with TickerProviderStateMixin {///动画最大值static double maxValue = 1000.0;late AnimationController controller;late Animation<double> animation;@overridevoid initState() {super.initState();controller =AnimationController(duration: const Duration(seconds: 1), vsync: this);animation = Tween(begin: 0.0, end: maxValue).animate(controller)..addListener(_animationListener);controller.repeat();}void _animationListener() {if (mounted) {setState(() {});}}@overrideWidget build(BuildContext context) {return LayoutBuilder(builder: (v1, v2) {Path path = Path();path.moveTo(50, 50);path.cubicTo(50, 50, 100, 300, 300, 400);return CustomPaint(size: Size(v2.maxWidth, v2.maxHeight),painter: Particle(path: path),);});}@overridevoid dispose() {controller.removeListener(_animationListener);controller.dispose();super.dispose();}
}class Particle extends CustomPainter {///点粒子,如果设置了点粒子,则只显示点粒子final Offset? point;///路径粒子,优先点粒子final Path? path;///粒子改变方式final ParticleChangeType type;///粒子的数量final int startNum;final int endNum;///粒子运行半径final int rr;///粒子大小半径final int r;///路径粒子密度,数值越大,密度越大final int pointDensity;Particle({this.path,this.type = ParticleChangeType.disappear,this.startNum = 100,this.endNum = 6,this.rr = 20,this.r = 1,this.point,this.pointDensity = 80,});@overridevoid paint(Canvas canvas, Size size) {if (point != null) {_bezierDraw(canvas, startNum, point!);} else if (path != null) {PathMetric? pathMetric1 = path!.computeMetric();if (pathMetric1 != null) {int length1 = pathMetric1.length.toInt();double diff = (startNum - endNum) / length1;if (length1 > pointDensity) {int gap = length1 ~/ pointDensity;if (gap == 0) {gap = 2;}for (int i = 0; i < length1.toInt(); i = i + gap) {int left = (startNum - diff * i).toInt();Tangent? tangent1 = pathMetric1.getTangentForOffset(i.toDouble());if (tangent1 != null) {Offset cur = tangent1.position;_bezierDraw(canvas, left, cur);}}} else {for (int i = 0; i < length1.toInt(); i++) {int left = (startNum - diff * i).toInt();Tangent? tangent1 = pathMetric1.getTangentForOffset(i.toDouble());if (tangent1 != null) {Offset cur = tangent1.position;_bezierDraw(canvas, left, cur);}}}}}}@overridebool shouldRepaint(covariant CustomPainter oldDelegate) {return true;}_bezierDraw(Canvas canvas, int left, Offset cur) {for (int j = 0; j < left; j++) {double mix = Random().nextDouble();int r = Random().nextInt(rr);double radians1 = j * 2 * pi / left;double x1 = r * cos(radians1) + cur.dx;double y1 = r * sin(radians1) + cur.dy;///计算出两点间中间点往上垂直两点距地的点的坐标//计算坐标系中起点与终点连线与x坐标的夹角的弧度值double radians2 = atan2(y1 - cur.dy, x1 - cur.dx);//根据三角函数计算出偏移点相对于起点为原的坐标系的X的坐标double centerOffsetPointX = cos(Random().nextInt(2) == 1? (45 * pi / 180 + radians2): (45 * pi / 180 - radians2)) *sqrt(2) *r /2;//根据三角函数计算出偏移点相对于起点为原的坐标系的Y的坐标double centerOffsetPointY = sin(Random().nextInt(2) == 1? (45 * pi / 180 + radians2): (45 * pi / 180 - radians2)) *sqrt(2) *r /2;///坐标系平移double moveX = centerOffsetPointX + cur.dx;double moveY = centerOffsetPointY + cur.dy;Path path2 = Path();path2.moveTo(cur.dx, cur.dy);path2.cubicTo(cur.dx, cur.dy, moveX, moveY, x1, y1);/*canvas.drawPath(path2,Paint()..color = Colors.redAccent..style = PaintingStyle.stroke,);*////画动画点PathMetric? pathMetric2 = path2.computeMetric();if (pathMetric2 != null) {double length2 = pathMetric2.length;Tangent? tangent2 = pathMetric2.getTangentForOffset(length2 * mix);if (tangent2 != null) {Offset cur2 = tangent2.position;canvas.drawCircle(Offset(cur2.dx, cur2.dy),(type == ParticleChangeType.stable? this.r: type == ParticleChangeType.disappear? this.r * (1 - mix): this.r * mix).toDouble(),Paint()..color = Colors.redAccent..maskFilter=const MaskFilter.blur(BlurStyle.normal, 2));}}}}
}///粒子运动的变换方式
enum ParticleChangeType {///稳定,粒子运动时大小不改变stable,///消散,由大到小消失不见disappear,///聚合,由小到大出现后直接消失together,
}

 主要思路:

利用flutter的画布绘图,随机根据Path生成一些点,然后绘制路径,然后绘制路径上每一个点往四周动画运动的小球,小球在运动到一定的距离后,会消失,周而复始,达到粒子生成与泯灭的效果。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/84345.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Vue 使用vue-cli构建SPA项目(超详细)

目录 一、什么是vue-cli 二&#xff0c;构建SPA项目 三、 运行SPA项目 前言&#xff1a; 在我们搭建SPA项目时候&#xff0c;我们必须去检查我们是否搭建好NodeJS环境 cmd窗口输入以下指令&#xff1a;去检查 node -v npm -v 一、什么是vue-cli Vue CLI&#xff08;Vu…

Qt/C++音视频开发53-本地摄像头推流/桌面推流/文件推流/监控推流等

一、前言 编写这个推流程序&#xff0c;最开始设计的时候是用视频文件推流&#xff0c;后面陆续增加了监控摄像头推流&#xff08;其实就是rtsp视频流&#xff09;、网络电台和视频推流&#xff08;一般是rtmp或者http开头m3u8结尾的视频流&#xff09;、本地摄像头推流&#…

短视频矩阵系统,短视频矩阵源码技术开发

开发短视频矩阵系统的源码需要以下步骤&#xff1a; 确定系统需求&#xff1a;根据客户的需求&#xff0c;确定系统的功能和特点&#xff0c;例如用户注册登录、视频上传、视频浏览、评论点赞等。 设计系统架构&#xff1a;根据系统需求&#xff0c;设计系统的整体架构&#x…

前端工程师路上的宝藏:不可错过的进阶必读文章!

JavaScript 《javascript高级程序设计》核心知识总结 必要性&#xff1a;⭐️⭐️⭐️⭐️ 难度&#xff1a;⭐️⭐️⭐️⭐️ 谏言&#xff1a;建议初学者先读一两遍红宝石书&#xff08;即JavaScript高级程序设计&#xff09;&#xff0c;犀牛书可以暂时不看&#xff08;…

csp初赛总结 那些年编程走过的坑 初高中信竞常考语法算法点

&#x1f618;个人主页&#xff1a;曲终酣兴晚的小书屋&#x1f496; &#x1f615;作者介绍&#xff1a;一个莽莽撞撞的&#x1f43b; &#x1f496;专栏介绍&#xff1a;日常生活&往事回忆 &#x1f636;‍&#x1f32b;️每日金句&#xff1a;祝大家心有山水不造作&…

typedef function<int (int,int)> func_t;

这段代码是C中用于创建函数类型别名&#xff08;function type alias&#xff09;的语法。让我们来逐步解释它&#xff1a; typedef: typedef 是C中的关键字&#xff0c;用于创建类型别名。它允许你为一个已存在的类型创建一个新的、易于使用的名称。 function: 这部分指定了要…

【Java 基础篇】Java同步代码块解决数据安全

多线程编程是现代应用程序开发中的常见需求&#xff0c;它可以提高程序的性能和响应能力。然而&#xff0c;多线程编程也带来了一个严重的问题&#xff1a;数据安全。在多线程环境下&#xff0c;多个线程同时访问和修改共享的数据可能导致数据不一致或损坏。为了解决这个问题&a…

【打印文件】python实现-附ChatGPT解析

1.题目 打印文件 时间限制: 1s 空间限制: 256MB 限定语言:不限 题目描述: 有5台打印机打印文件,每台打印机有自己的待打印队列。 因为打印的文件内容有轻重缓急之分,所以队列中的文件有1~10不同的优先级,其中数宁越大优先级越高。 打印机会从自己的待打印队列中选择优先级最…

【差旅游记】初见乌海湖

哈喽&#xff0c;大家好&#xff0c;我是雷工。 最近在乌海出差&#xff0c;有幸见到了传说中在沙漠中看海的“黄河明珠”——乌海湖。 前段时间一直有点忙&#xff0c;现在有点时间&#xff0c;趁还没忘光&#xff0c;简单整理记录下。 那是在上个月&#xff0c;2023年8月8号…

Flutter的路由router-页面跳转

文章目录 概念介绍基本路由&#xff08;Basic Routing&#xff09;跳转到某个页面弹出页面 命名路由&#xff08;Named Routing&#xff09;第三方路由管理库&#xff08;Third-Party Routing Libraries&#xff09; Android原生的路由Intent-based Routing&#xff08;基于Int…

停车场系统、智慧城市停车、智慧社区、物业管理、新能源充电、人脸门禁 uniapp 系统源码

1. 智慧停车 支持模式 封闭性单个停车场路边停车(车位级管理)大小场(场中场)&#xff0c;多场子并行或嵌套 所有者模式 统一平台管理总平台下子账号(区域代理)自建场地资源&#xff0c;自行维护数据总平台下子账号(区域代理)再分配和单个停车场管理人员(物业管理/维保/保安/财务…

【Spatial-Temporal Action Localization(七)】论文阅读2022年

文章目录 1. TubeR: Tubelet Transformer for Video Action Detection摘要和结论引言&#xff1a;针对痛点和贡献模型框架TubeR Encoder&#xff1a;TubeR Decoder&#xff1a;Task-Specific Heads&#xff1a; 2. Holistic Interaction Transformer Network for Action Detect…

stm32学习-芯片系列/选型/开发方式

【03】STM32HAL库开发-初识STM32 | STM概念、芯片分类、命名规则、选型 | STM32原理图设计、看数据手册、最小系统的组成 、STM32IO分配_小浪宝宝的博客-CSDN博客  STM32&#xff1a;ST是意法半导体&#xff0c;M是MCU/MPU&#xff0c;32是32位。  ST累计推出了&#xff1a…

七天学会C语言-第五天(函数)

1. 调用有参函数 有参函数是一种接受输入参数&#xff08;参数值&#xff09;并执行特定操作的函数。通过向函数传递参数&#xff0c;你可以将数据传递给函数&#xff0c;让函数处理这些数据并返回结果。 例1&#xff1a;编写一程序&#xff0c;要求用户输入4 个数字&#xf…

GO语言从入门到实战-Go语言课程介绍

为什么选择 Go 语言来完成这么大一个项目呢&#xff1f;我们不妨回到 Go 语言的源头看一看。 Go 语言的初步设想始于 2007 年&#xff0c;当时 Go 语言的三位创始人是想通过开发一种新型的语言来解决 Google 在软件开发中面临的问题&#xff1a; 多核硬件架构&#xff1b;超大…

MYSQL存储引擎基础知识介绍

下面重点介绍几种常用的存储引擎,并对比各个存储引擎之间的区别&#xff0c;以帮助读者理解 不同存储引擎的使用方式。 MyISAM MyISAM是 MySQL的默认存储引擎。MyISAM不支持事务、也不支持外键&#xff0c;其优势是访 问的速度快&#xff0c;对事务完整性没有要求或者以 SEL…

Postman应用——接口请求和响应(Get和Post请求)

文章目录 新增Request请求Get请求Post请求 Request请求响应Postman响应界面说明请求响应另存为示例&#xff08;模板&#xff09;Postman显示的响应数据清空请求响应数据保存到本地文件 这里只讲用的比较多的Get和Post请求方式&#xff0c;也可以遵循restful api接口规范&#…

uniapp 封装request请求

在request 文件夹 新建request.js import main from "main.js" export const request (options) > {return new Promise((resolve, reject) > {let token uni.getStorageSync(token)options.header.Authorization tokenuni.request({url: main.baseUrl op…

laravel-admin联动选择展示时ueditor样式错乱

问题 录入内容时&#xff0c;根据资源类型&#xff0c;展示不同的需要录入的内容&#xff0c;很常见的功能&#xff0c;但是在切换时&#xff0c;编辑器一直出不来&#xff0c;如图&#xff1a; 代码如下&#xff1a; $form->radio(type, 资源类型)->when(2, function…

Leetcode152. 连续子数组的最大乘积

力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 给你一个整数数组 nums &#xff0c;请你找出数组中乘积最大的非空连续子数组&#xff08;该子数组中至少包含一个数字&#xff09;&#xff0c;并返回该子数组所对应的乘积。 测试用例的答案是一个 32…