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

 更新时间:2022年08月09日 11:33:51   作者:十三点47  
这篇文章主要为大家介绍了Flutter绘制3.4边形之多边形渐变动画实现示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
(福利推荐:【腾讯云】服务器最新限时优惠活动,云服务器1核2G仅99元/年、2核4G仅768元/3年,立即抢购>>>:9i0i.cn/qcloud

(福利推荐:你还在原价购买阿里云服务器?现在阿里云0.8折限时抢购活动来啦!4核8G企业云服务器仅2998元/3年,立即抢购>>>:9i0i.cn/aliyun

正文

项目被优化了,人也跟着被优化了,正好趁这一个月整理整理关于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边形渐变动画的资料请关注程序员之家其它相关文章!

相关文章

  • IOS 中NSUserDefaults读取和写入自定义对象的实现方法

    IOS 中NSUserDefaults读取和写入自定义对象的实现方法

    这篇文章主要介绍了IOS 中NSUserDefaults读取和写入自定义对象的实现方法的相关资料,希望通过本文大家能够理解掌握这部分内容,需要的朋友可以参考下
    2017-09-09
  • 详解iOS 计步器的几种实现方式

    详解iOS 计步器的几种实现方式

    本篇文章主要介绍了详解iOS 计步器的几种实现方式,详细的介绍了两种可以获取计步数据的方法,有兴趣的可以了解一下
    2017-08-08
  • iOS中FMDB事务实现批量更新数据

    iOS中FMDB事务实现批量更新数据

    这篇文章主要为大家详细介绍了iOS中FMDB事务实现批量更新数据,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-11-11
  • ios实现简单随便移动的AR功能

    ios实现简单随便移动的AR功能

    这篇文章主要为大家详细介绍了ios实现简单随便走的AR功能,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-02-02
  • 提高iOS开发的小技巧和思路小结 (二)

    提高iOS开发的小技巧和思路小结 (二)

    这篇文章主要跟大家分享了关于提高iOS开发的一些小技巧和思路,通过本文总结的这些小技巧和思路相信对对大家开发iOS具有一定的参考价值,感兴趣的朋友们可以参考学习,下面来跟着小编一起学习学习吧。
    2017-04-04
  • iOS中只让textField使用键盘通知的实例代码

    iOS中只让textField使用键盘通知的实例代码

    本文通过实例代码给大家介绍了OS中只让textField使用键盘通知的操作方法,代码简单易懂,非常不错,具有参考借鉴加载,需要的的朋友参考下吧
    2017-07-07
  • 解决iOS验证码显示在左边问题

    解决iOS验证码显示在左边问题

    这篇文章主要介绍了iOS验证码显示在左边问题,本文给大家分享解决思路通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-03-03
  • iOS应用中UISearchDisplayController搜索效果的用法

    iOS应用中UISearchDisplayController搜索效果的用法

    这篇文章主要介绍了iOS应用中UISearchDisplayController搜索效果的用法,包括点击搜索出现黑条问题的解决方法,代码基于传统的Objective-C,需要的朋友可以参考下
    2016-02-02
  • IOS NSTimeInterval使用案例详解

    IOS NSTimeInterval使用案例详解

    这篇文章主要介绍了IOS NSTimeInterval使用案例详解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-08-08
  • iOS scrollview实现三屏复用循环广告

    iOS scrollview实现三屏复用循环广告

    这篇文章主要介绍了iOS scrollview实现三屏复用循环广告,从服务器请求的广告,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-01-01

最新评论

?


http://www.vxiaotou.com