flutter开发实战-Canvas绘图之Path路径动画

flutter开发实战-Canvas绘图之Path路径动画

flutter提供一块2D画布Canvas,Canvas内部封装了一些基本绘制的API,开发者可以通过Canvas绘制各种自定义图形。canvas上绘图,有多种不同的方式,常用的就是使用 Path。这里是flutter实现Path路径动画。

实现小球根据Path来做动画效果。

一、效果图

运行后效果图如下

在这里插入图片描述

二、代码实现

实现小球根据Path来做动画效果。
代码使用的是Stack+position进行,通过动画计算Position的top、left更改位置。

Path.computeMetrics
computeMetrics是路径中一个非常实用的操作,可以更具这个方法获得很多有价值的信息。比如路径上某点在路径上的位置、角度、路径长度等。

获取路径某个位置Position

  Offset calculate(value, path) {PathMetrics pathMetrics = path.computeMetrics();PathMetric pathMetric = pathMetrics.elementAt(0);value = pathMetric.length * value;Tangent pos = pathMetric.getTangentForOffset(value)!;return pos.position;}

创建Stack上的小球代码

class _MyHomePageState extends State<MyHomePage> {// 弹珠的widgetsList<BallAnimation> _marbleWidgets = [];void initState() {// TODO: implement initStatesuper.initState();}void dispose() {// TODO: implement disposesuper.dispose();}Widget build(BuildContext context) {// This method is rerun every time setState is called, for instance as done// by the _incrementCounter method above.//// The Flutter framework has been optimized to make rerunning build methods// fast, so that you can just rebuild anything that needs updating rather// than having to individually change instances of widgets.Size size = MediaQuery.of(context).size;return Scaffold(appBar: AppBar(// Here we take the value from the MyHomePage object that was created by// the App.build method, and use it to set our appbar title.title: Text(widget.title),),body: Container(width: size.width,height: size.height,alignment: Alignment.center,child: Stack(alignment: Alignment.center,children: [buildMarbleAnimation(context),],),),);}Widget buildMarbleAnimation(BuildContext context) {Size size = MediaQuery.of(context).size;return Container(width: size.width,height: size.height,alignment: Alignment.center,child: Stack(alignment: Alignment.center,children: buildWidgets(context),),);}List<BallAnimation> buildWidgets(BuildContext context) {Size size = MediaQuery.of(context).size;_marbleWidgets.clear();for(int index = 0; index < 10; index++) {BallAnimation ballAnimation = BallAnimation(screenSize: size);_marbleWidgets.add(ballAnimation);}return _marbleWidgets;}
}

实现根据Path更改Position的top与left代码

class BallAnimation extends StatefulWidget {const BallAnimation({super.key, required this.screenSize,});final Size screenSize;State<BallAnimation> createState() => _BallAnimationState();
}class _BallAnimationState extends State<BallAnimation>with TickerProviderStateMixin {late AnimationController _animateController;late Animation<double> _animation;// 球的Xlate Offset _ballOffset = Offset(0, 0);// 球的X,Ylate double _ballX = 0;late double _ballY = 0;Path path = Path();void initState() {// TODO: implement initState]super.initState();startRunAnimation();}void startRunAnimation() {runAnimation();}void runAnimation() {double randomXPos1 = (Random().nextInt(100)/100)*widget.screenSize.width;double randomYPos1 = (Random().nextInt(100)/100)*widget.screenSize.height;// path的moveTo方法path.moveTo(randomXPos1, randomYPos1);for(int index = 0; index < 10; index++) {double randomXPos = (Random().nextInt(100)/100)*widget.screenSize.width;double randomYPos = (Random().nextInt(100)/100)*widget.screenSize.height;// path的lineTo方法path.lineTo(randomXPos, randomYPos);}Duration duration = Duration(seconds: 20);Curve curve = Curves.linear;_animateController = AnimationController(vsync: this, duration: duration);//使用弹性曲线_animation = CurvedAnimation(parent: _animateController, curve: curve);_animation = Tween(begin: 0.0, end: 1.0).animate(_animation);_animateController.addListener(() {if (mounted) {setState(() {_ballX = calculate(_animation.value, path).dx;_ballY = calculate(_animation.value, path).dy;_ballOffset = Offset(_ballX, _ballY);});}});_animateController.addStatusListener((status) {if (status == AnimationStatus.completed) {_animateController.reset();_animateController.forward();}});_animateController.forward();}void dispose() {// TODO: implement dispose_animateController.dispose();super.dispose();}Widget build(BuildContext context) {return Positioned(top: _ballY,left: _ballX,child: Container(width: 80,height: 80,decoration: BoxDecoration(color: Colors.teal,borderRadius: BorderRadius.all(Radius.circular(40))),),);}Offset calculate(value, path) {PathMetrics pathMetrics = path.computeMetrics();PathMetric pathMetric = pathMetrics.elementAt(0);value = pathMetric.length * value;Tangent pos = pathMetric.getTangentForOffset(value)!;return pos.position;}
}

三、小结

flutter开发实战-Canvas绘图之Path路径动画

flutter提供一块2D画布Canvas,Canvas内部封装了一些基本绘制的API,开发者可以通过Canvas绘制各种自定义图形。canvas上绘图,有多种不同的方式,常用的就是使用 Path。这里是flutter实现Path路径动画。

学习记录,每天不停进步。

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

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

相关文章

php连接上mysql数据库该的配置方法

用mysql官方的管理工具workbench&#xff1a; 打开导出界面后&#xff0c;下一步&#xff0c;选择csv格式&#xff0c;导出后excel就能打开了 如果你需要在程序代码中导出&#xff0c;需要找到对应代码的excel处理库。 如php 的 phpExcel( 最新版已更名为 phpoffice/phpspread…

Databend 开源周报第 102 期

Databend 是一款现代云数仓。专为弹性和高效设计&#xff0c;为您的大规模分析需求保驾护航。自由且开源。即刻体验云服务&#xff1a;https://app.databend.cn 。 Whats On In Databend 探索 Databend 本周新进展&#xff0c;遇到更贴近你心意的 Databend 。 为指定列创建 B…

基于 Jieba 和 Word2vec 的关键词词库构建

最近有空&#xff0c;把论文中用到的技术和大家分享一下&#xff08;以组件化的形式&#xff09;&#xff0c;本篇将讲述如何从大量的语料中获取诸多关键词和构建关键词词库或 xx 关键词词库&#xff08;细分领域&#xff09;。举例以购物网站的在线评论作为语料库&#xff0c;…

搭建gitblit

这个就是资源搭建包不是很好找 搭建一台属于自己的Git服务器_51CTO博客_git搭建本地服务器 使用wget下载安装包 wget https://miracle-1306318206.cos.ap-shanghai.myqcloud.com/public/gitblit-1.9.1.tar.gz 如果资源找不到可以使用如下链接下载&#xff1a;链接: https:/…

Android 自定义CheckBox样式,设置切换背景图,类似于RadioButton

文章目录 概要自定义CheckBoX资源文件如下使用方法实现效果 概要 目前要实现类似于Radiobutton选择按钮&#xff0c;如果只有一个RadioButton&#xff0c;就不能和radio Group连用&#xff0c;导致选择没办法取消&#xff0c;如果要实现只能代码中进行操作&#xff0c;过于繁琐…

HCIA|详解Telnet协议

一、前言 今天翻到了之前写的Telnet协议的实验&#xff0c;由于该篇文章创作于开始写作的初期&#xff0c;文章结构简单、布局潦草&#xff0c;但实验内容是完整的&#xff0c;因此本篇文章将对Telnet技术进行详解&#xff0c;希望能够对大家提供帮助。在本文中&#xff0c;将从…

Redis高级篇(一)

分布式缓存 -- 基于Redis集群解决单机Redis存在的问题 单机的Redis存在四大问题&#xff1a; 1.Redis持久化 Redis有两种持久化方案&#xff1a;RDB持久化、AOF持久化 1.1.RDB持久化 什么是RDB持久化 RDB全称Redis Database Backup file&#xff08;Redis数据备份文件&am…

【笔记MD】

https://editor.csdn.net/md/?not_checkout1&articleId131798584 这里写自定义目录标题 https://editor.csdn.net/md/?not_checkout1&articleId131798584欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题&#xff0c;有助于目录的生成如何改变文本的样式插入…

开发工具篇第二十六讲:使用IDEA进行本地调试和远程调试

开发工具篇第二十六讲&#xff1a;使用IDEA进行本地调试和远程调试 Debug用来追踪代码的运行流程&#xff0c;通常在程序运行过程中出现异常&#xff0c;启用Debug模式可以分析定位异常发生的位置&#xff0c;以及在运行过程中参数的变化&#xff1b;并且在实际的排错过程中&am…

Cesium-源码打包1.106

在有Cesium源码打包的需求下&#xff0c;可以这样进行&#xff0c; 1.106的源码目录结构如下&#xff1a; 1.在下载的源码目录中运行 npm install 出现node_modules文件夹&#xff0c;然后我们就可以根据需求去修改源码&#xff0c;本文用的版本是1.106&#xff0c; packag…

K8s集群架构组件(3)

&#xff08;2&#xff09;node组件 kubelet&#xff1a;master排到node节点代表&#xff0c;管理本机容器 kube-proxy&#xff1a;提供网络代理&#xff0c;负载均衡等操作

linux 安装pytorch3d的坑

事实上&#xff0c;只要按照官方文档的说明就可以完美安装。其中坑的地方在于conda的管理可能会导致下载的版本不符合你的要求&#xff08;例如下载成了cpu版本、下载的cuda版本&#xff09;而同样尝试使用源码编译以及其他方式下载库都会导致同样的问题&#xff0c;这里主要的…