Flutter绘制3.4边形及多边形渐变动画实现示例

目录
  • 正文
    • 绘制3.4边形
    • 整数边形的绘制
    • 分数边形的绘制
    • 具体代码
    • 效果改进1
    • 效果改进2

正文

项目被优化了,人也跟着被优化了,正好趁这一个月整理整理关于flutter的一些东西。

绘制3.4边形

先看一下效果图:

起因是上上上上上个月浏览flutter的canvas相关内容时,点进去一个网站,看到一个让我眼前一亮的动效:

作者用的代码是swift的,我没细看,不过他文章里的一句话让我醍醐灌顶:

That is, we want the shape be asked to draw multiple times, each time with a different value for the sides parameter: 3, 3.1, 3.15, 3.2, 3.25, all the way to 4.

大意就是说我们想搞一个从三边形到四边形的动画,我们只需要画出3.1边形,3.2边形,3.3边形,一直画到4边形。

这句话真的让我醍醐灌顶,因为我看到这个动画,第一反应是需要计算每个顶点位置,从而做出动画;但是这句话让这个问题脱离了具体细节,将问题抽象化,数学化。只要我们定义出分数边形的绘制方法,我们就可以很简单的完成这个动画。

现在我们只要定义如何绘制分数边形就可以了。

整数边形的绘制

在定义绘制分数边形的绘制方法之前,我们先来看整数边形是如何绘制的:

绘制正三角形,我们会在圆上找出三等分点,然后依次连接这三个点,这就是正三角形的绘制方法。

而且绘制的时候我们通常会固定一个起点,然后从这个起点开始等分。

分数边形的绘制

分数边形的绘制也是一样的道理,比如3.1边形的绘制,我们需要找到四个点

我们先固定一个起点,然后从这个起点开始旋转(2*pi/3.1)个弧度,这样依次找到剩下三个点,(因为不是等分,所以可这样找下去可以找到无数个点,但我们只需要找四个点),而且当我们给到两个很相近的分数,比如3.1和3.11时,3.1边形对应的四个点和3.11对应的四个点,由于它们的起点是固定的,剩下各自的三个点对应的位置都是很接近的(因为3.1和3.11对应的弧度是很接近的),这样一直画到4.0边形,就完成了从三边形到四边形的渐变动画。

具体代码

获取多边形顶点

List<Offset> points = [];
List<Offset> getPolygonPoints1(double sides) {
    for (int i = 0; i < sides.ceil(); i++) {
      double x, y;
      x = radius * sin(i * 2 * pi / sides);
      y = -radius * cos(i * 2 * pi / sides);
      points.add(Offset(x, y));
    }
    return points;
}

获取到多边形顶点之后我们就可以在Custompaint的paint函数中将其绘制出来:

@override
  void paint(Canvas canvas, Size size) {
      Paint paint = Paint()
          ..color = const Color(0xFF47484B)
          ..style = PaintingStyle.stroke
          ..strokeWidth = 1
          ..isAntiAlias = true;
      List<Offset> points = getPolygonPoints1(progress);
      for (int i = 0; i < points.length; i++) {
      canvas.drawLine(
          points[i % points.length], points[(i + 1) % points.length], paint);
      }
}

可以看到效果如下:

但是如果我想要下图这种效果,当边数为奇数时,顶点位于最上方,边数由奇数变成偶数时,最上方的顶点分裂成两个,类似下图效果:

效果改进1

想要达到这种效果,我们只需要将代码改进一下,不再固定起始点,而是在边数由奇数变为偶数时,将起始点的弧度由(pi / sides)渐变为0,由偶数变位奇数时,起始点弧度由0变为(pi / sides)。

代码如下:

List<Offset> getPolygonPoints2(double sides) {
    for (int i = 0; i < sides.ceil(); i++) {
      double x, y;
      if (sides.ceil() % 2 == 0) {
        x = radius *
            sin(lerpDouble(0, (pi / sides), sides - sides.floor())! +
                i * 2 * pi / sides);
        y = -radius *
            cos(lerpDouble(0, (pi / sides), sides - sides.floor())! +
                i * 2 * pi / sides);
      } else {
        x = radius *
            sin(lerpDouble((pi / sides), 0, sides - sides.floor())! +
                i * 2 * pi / sides);
        y = -radius *
            cos(lerpDouble((pi / sides), 0, sides - sides.floor())! +
                i * 2 * pi / sides);
      }
      points.add(Offset(x, y));
    }
    return points;
}

此时效果如下:

但是还是有些不完美,我还想让多边形边数为偶数时,起始点是从最上方的边的中点一直渐变到最上方的点,就是下面这种效果:

效果改进2

此时我们只需要将多边形由偶数变为奇数时的起始点改为最上方边线的中点即可。 此时代码如下:

List<Offset> getPolygonPoints(double sides) {
    for (int i = 0; i < sides.ceil(); i++) {
      double x, y;
      if (sides.ceil() % 2 == 0) {
        if (sides.ceil() == sides) {
          x = radius * sin((pi / sides) + i * 2 * pi / sides);
          y = -radius * cos((pi / sides) + i * 2 * pi / sides);
        } else {
          x = radius *
              sin(lerpDouble(0, (pi / sides), sides - sides.floor())! +
                  i * 2 * pi / sides);
          y = -radius *
              cos(lerpDouble(0, (pi / sides), sides - sides.floor())! +
                  i * 2 * pi / sides);
        }
      } else {
        if (sides.ceil() == sides) {
          x = radius * sin(i * 2 * pi / sides);
          y = -radius * cos(i * 2 * pi / sides);
        } else {
          // 起始点位置单独计算
          if (i == 0) {
            double startY = -radius * cos(pi / sides);
            double endY = -radius;
            x = 0;
            y = lerpDouble(startY, endY, sides - sides.floor())!;
          } else {
            x = radius *
                sin(lerpDouble((pi / sides), 0, sides - sides.floor())! +
                    (i - lerpDouble(1, 0, sides - sides.floor())!) *
                        2 *
                        pi /
                        sides);
            y = -radius *
                cos(lerpDouble((pi / sides), 0, sides - sides.floor())! +
                    (i - lerpDouble(1, 0, sides - sides.floor())!) *
                        2 *
                        pi /
                        sides);
          }
        }
      }
      points.add(Offset(x, y));
    }
    return points;
  }

在这个基础上再画出对角线,加上缩放,就能达到我们一开始看到的最终效果了。

一些canvas的其他小demo

关于flutter canvas的其他效果,我后面会陆续分享出来,大家喜欢的话可以关注一下~

git地址

以上就是Flutter绘制3.4边形之多边形渐变动画实现示例的详细内容,更多关于Flutter绘制3.4边形渐变动画的资料请关注我们其它相关文章!

时间: 2022-08-09

Android&nbsp;Flutter利用CustomPaint绘制基本图形详解

目录 绘制矩形 绘制圆形 绘制椭圆 绘制任意形状 绘制弧形 总结 上一篇我们介绍了 CustomPaint 的基本概念和使用,可以看到 CustomPaint 其实和 前端的 Canvas基本上是一样的,实际上前端 Canvas 支持的绘制方法 CustomPaint 都支持,毕竟 CustomPaint 其实也是基于 Canvas 实现的.本篇我们来介绍 CustomPaint 基本图形的绘制. 绘制矩形 绘制矩形比较简单,方法定义如下: void drawRect(Rect rect, Pa

详解利用Flutter中的Canvas绘制有趣的图形

目录 简介 等边三角形构建重复之美 绘制彩虹 绘制五角星 总结 简介 上一篇我们介绍了使用 Flutter 的 Canvas 绘制基本图形的示例,简单的示例没什么好玩的,今天这一篇我们来点有趣的,我们会完成如下图形的绘制: 发现数学重复之美:使用等边三角形组合成彩虹伞面. 绘制彩虹. 绘制评分用的五角星. 通过这一篇,我们可以知道自定义形状绘制的基本原理,然后可以在这个基础上绘制你自己想要绘制的图形. 等边三角形构建重复之美 首先我们来绘制等边三角形,其实上一篇我们也有绘制等边三角形,只是那是将

Android Flutter绘制有趣的 loading加载动画

目录 前言 效果1:圆环内滚动的球 效果2:双轨运动 效果3:钟摆运动 总结 前言 在网络速度较慢的场景,一个有趣的加载会提高用户的耐心和对 App 的好感,有些 loading 动效甚至会让用户有想弄清楚整个动效过程到底是怎么样的冲动.然而,大部分的 App的 loading 就是下面这种千篇一律的效果 —— 俗称“转圈”. 本篇我们利用Flutter 的 PathMetric来玩几个有趣的 loading 效果. 效果1:圆环内滚动的球 如上图所示,一个红色的小球在蓝色的圆环内滚动,而且在往

Android利用Flutter path绘制粽子的示例代码

目录 前言 绘制 基本轮廓 粽叶 嘴巴 眼睛 腮红 手&脚 头巾 咸甜是一家 发声 动画控制嘴巴开合 用到的技术点 总结 前言 大家好,端午将至,首先提前祝小伙伴端午安康,端午作为中华民族的非常重要的传统节日,粽子那是必不可少的,但是你真的知道粽子的历史吗? 今天跟随本篇文章用Flutter path画一个会科普节日的的粽子吧- 绘制 基本轮廓 首先我们需要将粽子的基本轮廓绘制出来,通过图片可以看到粽子的轮廓是一个圆圆的三角形状, 本篇文章所有的图形都是用纯Path路径制作,这里我们可以将粽子的

Android Flutter绘制扇形图详解

目录 简介 CustomPaint介绍 CustomPainter介绍 paint介绍 shouldRepaint介绍 示例 使用CustomPaint 自定义Painter 绘制 触摸事件处理 动画实现 简介 在开发过程中通常会遇到一些不规则的UI,比如不规则的线条,多边形,统计图表等等,用那些通用组件通过组合的方式无法进行实现,这就需要我们自己进行绘制.可以通过使用CuntomPaint组件并结合画笔CustomPainter去进行手动绘制各种图形. CustomPaint介绍 Custom

详解Flutter如何绘制曲线,折线图及波浪动效

目录 正弦曲线绘制 波浪动效 曲线绘制 折线图 其他说明 总结 简介 上一篇用 Flutter 的 Canvas 画点有趣的图形我们介绍了使用 CustomPaint 绘制自定义形状,可以看到有了图形的平面绘制数学计算方法,我们可以画出所需的形状.本篇我们来介绍线条类图形的绘制,并且结合 Animation 实现了常见的波浪动效.通过本篇,你可以了解到: 正弦曲线的绘制 利用两条正弦曲线加上 Animation 实现波浪动效 曲线的一般绘制方法 折线图绘制 下面是最终实现的效果图,接下来我们一项

python绘制简单折线图代码示例

1.画最简单的直线图 代码如下: import numpy as np import matplotlib.pyplot as plt x=[0,1] y=[0,1] plt.figure() plt.plot(x,y) plt.savefig("easyplot.jpg") 结果如下: 代码解释: #x轴,y轴 x=[0,1] y=[0,1] #创建绘图对象 plt.figure() #在当前绘图对象进行绘图(两个参数是x,y轴的数据) plt.plot(x,y) #保存图象 plt

extjs4图表绘制之折线图实现方法分析

本文实例讲述了extjs4图表绘制之折线图实现方法.分享给大家供大家参考,具体如下: 本篇文章将介绍extjs中自带的图表 在本次案例中,提供一下功能: 1.从后端请求数据并运用到图表中,形成动态数据. 2.查询出每年各个月中人数. 请看下面代码: Ext.define('ChartLineTest', { extend: 'Ext.panel.Panel', autoScroll : true, selectYear:null,//定义年份 initComponent: function ()

C# 绘制实时折线图,波形图

此Demo是采用VS自带的Chart图表控件,制作实时动态显示的折线图,和波形图.本文仅供学习分享使用,如有不足之处,还请指正. 涉及知识点: Chart 控件,功能强大,可以绘制柱状图,折线图,波形图,饼状图,大大简化了对图的开发与定制. Chart控件的相关概念: ChartArea,表示图表区域,一个Chart可以绘制多个ChartArea,重叠在一起. Series ,表示数据序列,每个ChartArea可以有多个数据线.即,Series属于ChartArea. AxisX,AxisY,

Python 绘制可视化折线图

1. 用 Numpy ndarray 作为数据传入 ply import numpy as np import matplotlib as mpl import matplotlib.pyplot as plt np.random.seed(1000) y = np.random.standard_normal(10) print "y = %s"% y x = range(len(y)) print "x=%s"% x plt.plot(y) plt.show()

python绘制分布折线图的示例

用Python 绘制分布(折线)图,使用的是 plot()函数. 一个简单的例子: # encoding=utf-8 import matplotlib.pyplot as plt from pylab import * # 支持中文 mpl.rcParams['font.sans-serif'] = ['SimHei'] # 'mentioned0cluster', names = ['mentioned1cluster','mentioned2cluster', 'mentioned3clu

Android绘制动态折线图

所谓动态折线图,就是折线图能随着手指的滑动进行动态绘制,这里很定会产生动画效果.基于这个效果,这里使用SurfaceView进行制图. 实现步奏如下: (1): 这里新建一个绘图ChartView,继承SurfaceView并实现SurfaceHolder.Callback , Runnable接口,主要绘图工作在子线程中完成. (2):现实 SurfaceHolder.Callback接口的三个方法,并在 surfaceCreated中开启子线程进行绘图. (3):重写onTouchEvent

详解Flutter TabLayout 布局用法

Flutter是谷歌的移动UI框架,可以快速在iOS和Android上构建高质量的原生用户界面. Flutter可以与现有的代码一起工作.在全世界,Flutter正在被越来越多的开发者和组织使用,并且Flutter是完全免费.开源的. 本文重点给大家介绍Flutter TabLayout 布局用法,具体内容如下所示: 先上图 顶部TabBar 使用 flutter create xxxx 创建一个项目 打开项目文件夹,在 lib 目录里创建三个 dart 文件,内容分别如下 First.dart

详解Flutter WebView与JS互相调用简易指南

本文采用Flutter官方WebView插件:https://pub.dartlang.org/packages/webview_flutter WebView与JS互相调用是一个刚需,但是貌似现在大家写的文章讲的都不是很清楚,我这个简易指南简单粗暴地分为两部分:JS调用Flutter和Flutter调用JS,拒绝花里胡哨,保证一看就懂,一学就会. 开始之前先简单了解一下官方WebView所包含的API: onWebViewCreated:在WebView创建完成后调用,只会被调用一次: ini

详解flutter之网络请求dio,请求,拦截器简单示例

flutter一直很火的网络请求插件dio 直接上代码,写成一个类,可以直接使用 包含请求的封装,拦截器的封装 import 'package:dio/dio.dart'; import 'dart:async'; import 'dart:io'; import './apidomain.dart'; import './httpHeaders.dart'; import 'package:shared_preferences/shared_preferences.dart'; class D

详解使用python绘制混淆矩阵(confusion_matrix)

Summary 涉及到分类问题,我们经常需要通过可视化混淆矩阵来分析实验结果进而得出调参思路,本文介绍如何利用python绘制混淆矩阵(confusion_matrix),本文只提供代码,给出必要注释. Code​ # -*-coding:utf-8-*- from sklearn.metrics import confusion_matrix import matplotlib.pyplot as plt import numpy as np #labels表示你不同类别的代号,比如这里的de