资讯专栏INFORMATION COLUMN

项目开发中的贝塞尔曲线

Tangpj / 1293人阅读

摘要:附加要求,飞行曲线,飞机先加速,然后减速抵达终点,飞行途中,需要转换飞机朝向,飞行途中,飞机渐渐变小体验网易邮箱大师电脑版实现方法飞行曲线我们选择了二次贝塞尔曲线,原因是简单,可计算。

本文由邹启文授权网易云社区发布。

邮箱大师PC版中,设计师提出了一个很妙的想法: 发信时,出现一个飞机,从写信中央飞往进度目的地。

附加要求:
1,飞行曲线,飞机先加速,然后减速抵达终点
2,飞行途中,需要转换飞机朝向
3,飞行途中,飞机渐渐变小
体验:网易邮箱大师电脑版

实现方法:

飞行曲线

我们选择了二次贝塞尔曲线,原因是简单,可计算。
数学公式:B(t) = (1-t)^2 P0 + 2 t (1-t) P1 + t^2 *P2, t=[0,1]

(图片来源于网络,此处是为了讲解清楚)

已知起飞点P0,终点P2,起飞角度(或斜率,切线P0P1),降落角度(或斜率,切线P1P2),求P1
将起飞角度转换(k=tan(θ))成斜率k1,降落角度转成斜率k2,根据斜率公式y=k*x+b可得
P0.y = k1 * P0.x + b1;
P1.y = k1 * P1.x + b1;
P2.y = k2 * P2.x + b2;
P1.y = k2 * P1.x + b2;
至此,便可求得P1坐标。(可调整角度(或k1,k2)以满足实际要求)

曲线虽然推导出来,但是,飞机先加速然后减速,如何实现呢?

注意观察,公式中t的取值范围是0~1,我们可以让飞机在前面小部分时间走过大部分距离,后面
大部分时间走过小部分距离来做到。
为了灵活调整,以及总时间固定的情况下,我们选择了一种简单的方法,将时间分片,人为的构造
出一段前面加速后面减速的时间曲线。

示例:
const int kPiece[] = { 10,20,30,45,65,90,70,45,40,35,30,25,22,20,19,18,17,16,15 };
定时器设置为10ms,每隔10ms,计算一次t=kPiece(0~i) / kPiece(0~N) * T;
kPiece(0~i)为前i项和,kPiece(0~N)为总和,T为固定的总时间

飞机朝向

飞机的头要随着曲线改变朝向。很显然,这个朝向就是曲线的切线方向。
求切线,正确的方式是求导。
在这里,我们选择了一种简单的方法:
记住当前点和上一点,然后计算2点的斜率,再转换成角度。

飞机大小

飞机大小变化没有严格要求,可采取线性变化,在总时间T内从1.0到0.25(根据素材大小决定),恰好做到与曲线同时变化结束。

特别注意
I、起飞角度转换成斜率,在计算机世界,其坐标系与数学中的坐标系不一致,X轴一致,而Y轴相反,所以角度可能是负数(比如起始时往左飞行)
II、飞机朝向,斜率转换成角度时,从A到B,B相对于A的位置可在4个象限,所以角度可能存在负角度,与此同时,素材中飞机也有个角度,那么绘制时,注意矫正角度
III、飞机降落时角度可能不正确(如从上方降落)。实际应用时,由于飞机变小且速度较快,而且降落时调整了角度,所以此问题不明显。如要保证飞机降落角度一定不变,可以考虑三次贝塞尔曲线

Gdiplus绘制飞机

Gdiplus::Graphics g(dc);
Gdiplus::PointF center(cx / 2, cy / 2);  // cx、cy为素材宽度和高度
g.TranslateTransform(center.X, center.Y);  // 转换坐标系
g.RotateTransform(angle_);  // 旋转角度
g.SetInterpolationMode(Gdiplus::InterpolationModeHighQualityBilinear);
g.ScaleTransform(scale_, scale_);  // 缩放
g.TranslateTransform(-center.X, -center.Y);
g.DrawImage(plane_.get(), 0, 0);  // 绘制图片

免费领取验证码、内容安全、短信发送、直播点播体验包及云服务器等套餐

更多网易技术、产品、运营经验分享请访问网易云社区。

文章来源: 网易云社区

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/25342.html

相关文章

  • 如何反转CSS中的塞尔曲线

    摘要:我们并不需要知道贝塞尔曲线背后的所有数学知识。我们可以使用相同的并设置并反转贝塞尔曲线,这样就实现了在正反两个方向上使用同一个的效果。我们来看看如何计算反向的贝塞尔曲线。 首先来看一看我之前写的一个CSS轮播动画效果,为了让切换时动画的过渡更加的平滑我在animation-timing-function属性中并没有使用CSS提供的各种关键词,而使用了cubic-bezier(贝塞尔)函...

    zhangqh 评论0 收藏0
  • 如何反转CSS中的塞尔曲线

    摘要:我们并不需要知道贝塞尔曲线背后的所有数学知识。我们可以使用相同的并设置并反转贝塞尔曲线,这样就实现了在正反两个方向上使用同一个的效果。我们来看看如何计算反向的贝塞尔曲线。 首先来看一看我之前写的一个CSS轮播动画效果,为了让切换时动画的过渡更加的平滑我在animation-timing-function属性中并没有使用CSS提供的各种关键词,而使用了cubic-bezier(贝塞尔)函...

    nicercode 评论0 收藏0
  • 如何反转CSS中的塞尔曲线

    摘要:我们并不需要知道贝塞尔曲线背后的所有数学知识。我们可以使用相同的并设置并反转贝塞尔曲线,这样就实现了在正反两个方向上使用同一个的效果。我们来看看如何计算反向的贝塞尔曲线。 首先来看一看我之前写的一个CSS轮播动画效果,为了让切换时动画的过渡更加的平滑我在animation-timing-function属性中并没有使用CSS提供的各种关键词,而使用了cubic-bezier(贝塞尔)函...

    amc 评论0 收藏0
  • 初识塞尔曲线

    摘要:贝塞尔曲线被广泛用于制图软件中。多边二次贝塞尔曲线可以看到有两个控制点,这样连续画出来了。如果前一个曲线不存在,当前点就是第一个控制点在中使用绘制二次贝塞尔曲线,参数分别为控制点和终点的值。绘制三次贝塞尔曲线。 贝塞尔曲线在CSS动画中和canvas、svg绘图中都是比较重要的一个东西!所以我来好好的小结一下关于它的一些东西。 什么是贝塞尔曲线 贝塞尔曲线于1962,由法国工程师皮埃尔...

    MasonEast 评论0 收藏0
  • 翻译 | 深入理解CSS时序函数

    摘要:一条正在绘制中的三次方贝塞尔曲线因为该曲线由四个点形成,我们将其称为三次方贝塞尔曲线,而不是二次方曲线三个点或四次方曲线五个点。现在终于可以将贝塞尔曲线收入囊中了,也已经对这 作者:Nicolas(沪江前端开发工程师)本文原创翻译,转载请注明作者及出处。 各位,赶紧绑住自己并紧紧抓牢了,因为当你掌握了特别有趣但又复杂的CSS时序函数之后,你将会真正体验到竖起头发般的兴奋感受。 好吧,本...

    Little_XM 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<