Flutter万花尺效果,梦回童年

3,768 阅读2分钟

背景

在某短视频上刷到一个万花轮的视频,优美的线条一下把老夫拉回了2005年,小时候的女神小花拿着她的新玩具跟我说,看我给你画一朵超级漂亮的花 VID_20210927145712.gif 不得不说,这东西虽小但对于当时的我来说却是非常震撼,不愧是我的女神能拥有这么神奇的玩意。那个时候的我一定万万没想到,时隔多年后,老夫竟然会用程序去破解女神的“魔法”。

不记得哪个伟人说过,看似复杂的表面背后的原理往往很简单。

好的,仔细观察一下,发现确实很简单只有两点需要解决就能实现这个神奇的效果:

  1. 推导出笔尖的点和旋转角的公式,即可根据角度的旋转获得所有点,连接成线即可。
  2. 手指在屏幕上滑动时,根据上一个点和当前点的坐标计算出旋转的角度

知识储备

内旋轮

内旋轮线(hypotrochoid)是追踪附着在围绕半径为 R 的固定的内侧滚转的半径为 r 的圆上的一个点得到的转迹线,这个点到内部滚动的圆的中心的距离是d。

80cb39dbb6fd5266c7dacc33ab18972bd4073627.gif

公式推导视频: 【数学】美妙的万花尺与旋轮线(下) | 使用manim 自制的3b1b风格数学视频_哔哩哔哩_bilibili

至于怎么推导出来的大家看这个视频就行了,up主讲的非常明白。直接贴公式:

image.png image.png 这里我们得到坐标和θ角度的参数方程为:

x=(R-r)cos(θ)+dcos((R-r)/r*θ)

y=(R-r)sin(θ)-dsin((R-r)/r*θ)

夹角计算

万花轮的转动都靠他来计算转动角度

第一个参数传入中心点,第二个参数是开始点,第二个参数是结束点。

double angle(Offset cen, Offset first, Offset second) {
  double dx1, dx2, dy1, dy2;

  dx1 = first.dx - cen.dx;
  dy1 = first.dy - cen.dy;
  dx2 = second.dx - cen.dx;
  dy2 = second.dy - cen.dy;

  // 计算三边的平方
  double ab2 = (second.dx - first.dx) * (second.dx - first.dx) +
      (second.dy - first.dy) * (second.dy - first.dy);
  double oa2 = dx1 * dx1 + dy1 * dy1;
  double ob2 = dx2 * dx2 + dy2 * dy2;

  // 根据两向量的叉乘来判断顺逆时针
  bool isClockwise = ((first.dx - cen.dx) * (second.dy - cen.dy) -
          (first.dy - cen.dy) * (second.dx - cen.dx)) >
      0;

  // 根据余弦定理计算旋转角的余弦值
  double cosDegree =
      (oa2 + ob2 - ab2) / (2 * Math.sqrt(oa2) * Math.sqrt(ob2));

  // 异常处理,因为算出来会有误差绝对值可能会超过一,所以需要处理一下
  if (cosDegree > 1) {
    cosDegree = 1;
  } else if (cosDegree < -1) {
    cosDegree = -1;
  }

  // 计算弧度
  double radian = Math.acos(cosDegree);

  // 计算旋转过的角度,顺时针为正,逆时针为负
  return isClockwise ? radian : -radian;
}

接下来就可以为所欲为了

完成效果

Record_2021-09-27-14-28-39_fdf5fd47189ebc7911f5db.gif

代码地址:github.com/AYoungXXX/I…