文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

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

2022-11-13 14:39

关注

正文

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

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-移动开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯