技术分享 | 一条神奇的曲线——贝塞尔曲线在前端的应用

1ab760f92d034e07dba7bf8dfbeef3db.png

3062edc800886c608940a8b722699199.png

源宝导读:在前端的开发中我们经常会遇到利用贝塞尔曲线帮助我们完成前端的动画和图形绘制,但是对其中的一些参数配置是一头雾水。本文将从贝塞尔曲线的原理讲起,由浅入深剖析一阶到多阶贝塞尔的实现原理,最后从三个方向来介绍它的实际应用。

一、IOS图标莫名的舒适感

先来对比下面两张图:

e835f0b21b719c28cb33f323dfbad933.png

如果你用过苹果手机就都会有一种感觉,很多安卓手机的图标都会像左侧图标这样——倒角和直线的过渡处有些许不自然;而现在流行的IOS系统图标都是右侧的这种,圆润的倒角,这种就是有一种说不出来哪里来的舒适感:苹果的图标为什么看起来就是比一般的安卓图标要高级?

在IOS6以及以前的版本上,苹果都是用的倒圆角这种图标;但是2013年6月苹果在IOS7发布会上,苹果将iOS上标志性的圆角图标轮廓作了更新,将工业设计中的曲线连续概念应用到了视觉设计之上,而这个曲率连续的线,就是我们今天要提到的——贝塞尔曲线。

二、历史起源

贝塞尔曲线(Bézier curve),又称贝兹曲线或贝济埃曲线,是应用于二维图形应用程序的数学曲线。贝塞尔曲线于1962年由法国工程师皮埃尔·贝塞尔(Pierre Bézier)所广泛发表,他运用贝塞尔曲线来为汽车的主体进行设计。现在主流的曲线设计基本都会用到这条曲线;常用的矢量图形软件都会通过它来精确画出曲线,比如ps的钢笔工具等。

三、数学原理

这条线到底神器在哪?在日常开发中,我们常用的是二次贝塞尔曲线和三次贝塞尔曲线,二次贝塞尔曲线只需要用到三个点,即可绘制出一条的平滑曲率过度自然的曲线;而苹果手机的边框和图标的倒角设计则用到了四个点,就完成了近乎完美的曲线倒角,接下来我们将深入的了解原理看看这条线是如何实现的。

1)向量:

在了解贝塞尔曲线之前,需要先了解一个定义向量:

向量指具有大小和方向的量,它可以形象化地表示为带箭头的线段,二维里面向量是一个[x,y] ,三维则是[x,y,z];

重要的事情说三次!下面定义里所有介绍的P0P1...Pn,ABC..都是向量!都是向量!都是向量!(目前只讨论二维)

2)一阶贝塞尔曲线和多阶贝塞尔曲线:

下图是一到四阶的贝塞尔曲线的示意图

e2d645150bab2f7cd079ebb700115611.png

① 一阶:

其实很简单,看上图第一个图形,点A 随着时间t 在P0到P1上运动,所有点的集合就是一次贝塞尔曲线。

用向量的角度来看:

一次贝塞尔曲线 B(t),P0P1线段上随着时间t的变化( 0≤ t ≤1 ), P0表示向量 [x0 ,y0] P1表示向量 [x1, y1], A的值B(t)即为公式:

A = P0 + (P1-P0)*t

A = (1-t)P0 + t*P1

B(t) = (1-t)P0 + t*P1

结论:一阶贝塞尔曲线实际就是一条线段。

② 二阶:

他的定义是这样的:

由P0至P1的连续点A,描述一条线段;由P1至P2的连续点B,描述一条线段;由A至B的连续点C:B(t) 描述一条二次贝塞尔曲线。

那么这些点肯定遵守下面的规则,

t = (A - P0) / (P1 - P0) = ( B- P1) / (P2 - P1) =  ( C - A ) / (B - A)

最终的公式如下:

A = (1-t)P0 + t*P1

B = (1-t)P1 + t*P2

C = (1-t)A + t*B

C = (1-t)( (1-t)P0 + t*P1 )  + t * ( (1-t)P1 + t*P2 )

C = (1-t)²P0 + 2t(1-t)P1 + t²P2;0≤t≤1

B(t) = (1-t)²P0 + 2t(1-t)P1 + t²P2;0≤t≤1

结论:二阶的贝塞尔通过在控制点之间再采点的方式实现降阶, 每一次选点都是一次的降阶。

③ 三阶:

理解了二阶以后,三阶可以依葫芦画瓢很快得出

A = (1-t)P0 + t*P1

B = (1-t)P1 + t*P2

C = (1-t)P2 + t*P3

D = (1-t)A + t*B

E = (1-t)B + t*C

F = (1-t)D + t*E

F = ....

结论:这个不就是递归嘛?

总结:

两个点对应一阶的贝塞尔曲线,三个点对应二阶,四个点对应三阶;

每一次的计算都一个降阶计算,高阶的贝塞尔可以通过不停的递归直到一阶。

n个控制点对应着n-1阶的贝塞尔曲线,并且可以通过递归的方式来绘制。

3)公式

通用公式:

8338edff8f36bb32c28e244eb08e4c8e.png

或者导数表示:

854d7bcc457ed813ee9528851c3931c2.png

感兴趣的同学可以下去研究一下,这里就不做过于深入的研究了。

四、贝塞尔曲线在前端的应用

贝塞尔曲线在web前端主要在三处会用到:分别是css,svg,canvas

1)     svg

svg的path路径d属性,支持二次(二阶)贝塞尔曲线和三次(三阶)贝塞尔曲线,缩写:

C和Q,例如:

Q 300 300, 500 100  二阶

C 200 200, 400 200,  500 100 三阶

我们先来看看一个demo,如下图的曲线:

d1f4549114ee0bbd753e5c27ec96fd53.png

要实现上图的效果,看下图第二行代码svg的path属性当中 d的值:

M100 100 Q 300 300, 500 100  实际就是对应的二次贝塞尔曲线的,三个点:

  •  第一个点:Q 前面的 100 100 起始点对应P0,

  •  第二个点:Q后面第一个点 300 300 对应控制点P1

  •  第三个点:Q后面的第二个点 500 100  对应结束点 P2

依此类推:类ball02:

M100 100 C 200 200, 400 200,  500 100  就是对应的三次贝塞尔曲线的,四个点:

  •   第一个点:C 前面的M 100 100 起始点对应P0

  •   第二个点:C后面第一个点 200 200  对应控制点P1

  •   第三个点:C后面第二个点 400 200  对应结束点 P2

  •   第四个点:C后面第三个点 500 100  对应结束点 P3

放代码:

6aa1ffa27cc614f53f2650d02d0d5875.png

补充小知识点:

下面的命令可用于路径path的d属性和offset-path的path属性:

M = moveto

L = lineto

H = horizontal lineto

V = vertical lineto

C = curveto

S = smooth curveto

Q = quadratic Belzier curve

T = smooth quadratic Belzier curveto

A = elliptical Arc

Z = closepath

属于贝塞尔曲的有:

C S Q T

2)    css3

① offset-path路径

offset-path css的移动路径  可以用path的简写语法, 上面的svg的代码已写明

就是如下这种形式

offset-path: path('M100 100 Q 300 300, 500 100')

② cubic-bezier函数

函数 css3的cubic-bezier函数,主要就是在:

  •  animation-timing-function(设置动画将如何完成一个周期)

  •  transition-timing-function, 属性(设置动画过渡的效果)当中使用

含义 cubic-bezier(x1,y1,x2,y2)函数具体含义如下,如下对应贝塞尔曲线的P0,P1,P2,P3

  •   P0:默认值 (0, 0)

  •   P1:动态取值 (x1, y1)

  •   P2:动态取值 (x2, y2)

  •   P3:默认值 (1, 1)

技巧 在css3中我们常用的几个过渡效果其实都是用贝塞尔曲线的形式来表示的,这些方法名就叫缓动函数(文章末尾会附上缓动函数):

  •   ease: cubic-bezier(0.25, 0.1, 0.25, 1.0)

  •   linear: cubic-bezier(0.0, 0.0, 1.0, 1.0)

  •   ease-in: cubic-bezier(0.42, 0, 1.0, 1.0)

  •   ease-out: cubic-bezier(0, 0, 0.58, 1.0)

  •   ease-in-out: cubic-bezier(0.42, 0, 0.58, 1.0)

注意的点 :

css3的贝塞尔曲线只有2阶和3阶的,并且将贝塞尔曲线做了一个限制:除了所有参数必需,参数是数字值以外;x1 和 x2 需要是 0 到 1 的数字。比较常见transitio的动画例如:宽度大小变化,颜色渐变,位置移动,内外边距等,animation的话可以结合@keyframe 实现一些关键帧动画,效果更好

Demo:

292aec244092b2fcc6021642f928ed09.png

3)    canvas

canvas比较简单,语法如下:

1. 二阶:quadraticCurveTo(x1,y1, x2,y2)

2. 三阶:bezierCurveTo(x1,y1, x2,y2, x3,y3)

上面的二阶,三阶 和 svg的 C,Q 是一样的语法,就不赘述了。

有一个波浪的效果这里全部是用canvas绘制的,代码贴在文章末尾。

c3c51a8e7c647b0c8f3a12c818114521.png

具体代码:

分三块:

1.dom区域:定义容器和尺寸,这个很好理解。

90932c0072d6c88404c6819f8767e394.png

第二个区域:绘制外圈的圆形drawCircle和波浪效果 drawSin的方法。

6bee767556bfecceb0173270b906602b.png

第三个区域:绘制动画,利用requestAnimationFrame方法不断的重新绘制波浪效果(animation方法),不停的重复累加X轴横向位置,这样就可以实现一个不断的波浪。

24cb8d8ae38a147f0f407bb97022997f.png

五、写在结尾的话

贝塞尔曲线这条神器的曲线在前端的应用还是相当广泛的,除了常见的css动画,过渡效果,在svg和canvas的动画当中也必不可少,掌握上述的三个方向,对面大部分的场景,前端的同学都能够游刃有余的去应付。

文章如有纰漏可以在评论里指正交流。

文中用到的代码:

链接: https://pan.baidu.com/s/1aMFK4Dehiz5KjddxN704vw  密码: b404

1. 曲线篇: 贝塞尔曲线  https://zhuanlan.zhihu.com/p/136647181

2. svg路径绘制  http://svg.wxeditor.com/

3. 缓动函数 https://www.xuanfengge.com/easeing/easeing/

另外附上css3 cubic-bezier函数 缓动效果集合:

  $easeInSine: cubic-bezier(0.47, 0, 0.745, 0.715);

  $easeOutSine: cubic-bezier(0.39, 0.575, 0.565, 1);

  $easeInOutSine: cubic-bezier(0.445, 0.05, 0.55, 0.95);

  $easeInQuad: cubic-bezier(0.55, 0.085, 0.68, 0.53);

  $easeOutQuad: cubic-bezier(0.25, 0.46, 0.45, 0.94);

  $easeInOutQuad: cubic-bezier(0.455, 0.03, 0.515, 0.955);

  $easeInCubic: cubic-bezier(0.55, 0.055, 0.675, 0.19);

  $easeOutCubic: cubic-bezier(0.215, 0.61, 0.355, 1);

  $easeInOutCubic: cubic-bezier(0.645, 0.045, 0.355, 1);

  $easeInQuart: cubic-bezier(0.895, 0.03, 0.685, 0.22);

  $easeOutQuart: cubic-bezier(0.165, 0.84, 0.44, 1);

  $easeInOutQuart: cubic-bezier(0.77, 0, 0.175, 1);

  $easeInQuint: cubic-bezier(0.755, 0.05, 0.855, 0.06);

  $easeOutQuint: cubic-bezier(0.23, 1, 0.32, 1);

  $easeInOutQuint: cubic-bezier(0.86, 0, 0.07, 1);

  $easeInExpo: cubic-bezier(0.95, 0.05, 0.795, 0.035);

  $easeOutExpo: cubic-bezier(0.19, 1, 0.22, 1);

  $easeInOutExpo: cubic-bezier(1, 0, 0, 1);

  $easeInCirc: cubic-bezier(0.6, 0.04, 0.98, 0.335);

  $easeOutCirc: cubic-bezier(0.075, 0.82, 0.165, 1);

  $easeInOutCirc: cubic-bezier(0.785, 0.135, 0.15, 0.86);

  $easeInBack: cubic-bezier(0.6, -0.28, 0.735, 0.045);

  $easeOutBack: cubic-bezier(0.175, 0.885, 0.32, 1.275);

  $easeInOutBack: cubic-bezier(0.68, -0.55, 0.265, 1.55);

------ END ------

作者简介

曹同学: 数据分析平台的开发工程师,目前负责天际平台相关开发工作。

也许您还想看:

技术分享|Java SDK动态数据源和上下文机制

技术分享|NodeJS分布式链路追踪实现

技术分享 | Java SDK 元数据驱动的事件通信架构

技术分享|Hangfire深度实践

技术分享 | APT结合JavaPoet生成模板化Java源代码文件

技术分享 | 玩转高效UI自动化测试

更多明源云·天际开放平台场景案例与开发小知识,可以关注明源云天际开发者社区公众号:

【建模】文档服务提供高保真打印模式

明源云·天际硬核技术认可:获华为鲲鹏技术认证书

天际·开发者社区“重装发布”!

2ebf9b38d9f21cd220dc8e99eed9df19.png

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/295187.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

女生来大姨妈该怎么哄她?

1 这捞人速度!▼2 老师:我怀疑你在内涵我!?(素材来源网络,侵删)▼3 就很出戏(素材来源网络,侵删)▼4 分手到底有多痛苦?▼5 家长会上看到的纸…

OAuth 2.1 的进化之路

背景2010年, OAuth 授权规范 1.0 (rfc 5849) 版本发布, 2年后, 更简单易用的 OAuth 2.0 规范发布(rfc 6749), 这也是大家最熟悉并且在互联网上使用最广泛的版本, 在2012年的时候, iPhone 5 是全新的, 微软最新的浏览器还是 IE9, 单页面应用在当时还被称作…

中科院超牛的物理学家,摇滚界无人不知的“李白”,你一定听过他的歌!

全世界只有3.14 % 的人关注了爆炸吧知识一个热爱音乐的科研工作者最近,有不少模友在后台问,如何如何去平衡好学习/工作和兴趣爱好之间的关系?很多人会说这么简单的问题,为什么还要问?其实并不简单,在现实生…

Nginx源码安装及应用

一:Nginx简介: Nginx ("engine x") 是一个高性能的HTTP和反向代理服务器。在高连接并发的情况下,Nginx是Apache服务器不错的替代品。 Nginx作为负载均衡服务器:Nginx 既可以在内部直接支持Rails和PHP 程序对外进行服务&…

宝藏好物gRPCurl

gRPCurl简介gRPCurl[1]是一个与gRPC服务器交互的命令行工具,可认为是gRPC的curl工具。gRPCurl用于从命令行调用gRPC服务器支持的RPC方法,gRPC使用二进制编码(protobuf), 不能利用常规的curl工具(早期的curl版本还不支持HTTP/2)。1. gRPCurl工具接受json编…

你的输入法都暴露了些啥?

1 三哥对柠檬茶下手了要不要来一杯?▼2 能成功求婚的应该就是真爱了吧?▼3 气泡的花样玩法▼4 很正确?▼5 高手过招!牛▼6 幽默中带着点死亡气息▼7 输入法:我暴露了一切▼你点的每个赞,我都认真当成了…

从 ThreadLocal 到 AsyncLocal

前些天跟大佬们在群里讨论如何在不使用构造函数,不增加方法参数的情况下把一个上下文注入到方法内部使用,得出的结论是 AsyncLocal 。感叹自己才疏学浅,居然才知道有 AsyncLocal 这种神器。于是赶紧恶补一下。ThreadLocal 要说 AsyncLocal 还…

Sersync+Rsync 增量实时同步

准备环境: rsync服务器:172.16.3.21sersync2服务器:172.16.3.23一、 rsync服务器先把原来的rsync包删掉yum remove rsync-2.6.8-3.1 -y,然后到http://rsync.samba.org/下载rsync包我用的包如下图所示利用securecrt上传本地[rootacong tongbu1…

浅谈RBF函数

所谓径向基函数 (Radial Basis Function 简称 RBF), 就是某种沿径向对称的标量函数。 通常定义为空间中任一点x到某一中心xc之间欧氏距离的单调函数 , 可记作 k(||x-xc||), 其作用往往是局部的 , 即当x远离xc时函数取值很小。 最常用的径向基函数是高斯核函数 ,形式为 k(||x-xc…

一个彻底改变世界的思想

全世界只有3.14 % 的人关注了爆炸吧知识因随机性的到来阔然开朗蒙特卡罗赌场蒙特卡罗(Monte Carlo)是摩纳哥公国(Principality of Monaco)的一座城市。摩纳哥公国坐落在法国的东南方,总面积为2.02平方公里,…

Cookies

一,前言 Cookies想必所有人都了解, 但是未必所有人都精通。本文讲解了Cookies的各方面知识。 二,基础知识 1.什么是Cookies Cookie 是一小段文本信息,伴随着用户请求和页面在 Web 服务器和浏览器之间传递。Cookie 包含每次用户访问…

用字符串表达式访问JSON数据(java,fastjson)

2019独角兽企业重金招聘Python工程师标准>>> //单元科技-www.ccell.com.cn 技术部,开源 //XML数据有XPATH 如"root/rows[id1]/name" //在JS中JSON数据可以对象方式访问 //java中怎么 用字符串表达式访问JSON数据? 找了很久没有找到,自己写一个,以减小代…

怎样分辨谁才是朋友圈里的真·贵族?

不是我不明白,这世界变化快但在这个看1分钟视频都要2倍速的世界里有一群人却仍然愿意每天花5分钟阅读2000字以上的文字信息这是多么高贵的一种精神所以高贵的你,值得更好的内容今天我们精选出8个优质公号他们有趣有料、有思想有温度绝对值得你的关注长按…

Android之如何解决Android studio运行出现的HAX kernel modules is not installed

HAX kernel modules is not installed 很久之前,我安装了Android studio,运行时控制台打印出这个,emulator:ERROR:x86 emulation currently requires hardware acceleration! Please ensure Intel HAXM is properly installed and useble, CPU acceleration statis:HAX kern…

Elastic AMP监控.NET程序性能

什么是Elastic AMPElastic APM 是一个应用程序性能监控系统。它可以请求的响应时间、数据库查询、对缓存的调用、外部 HTTP 请求等的详细性能信息,可以实时监控软件服务和应用程序。这可以帮助我们快速查明和修复性能问题。Elastic APM 还会自动收集未处理的错误和异…

asp.net 检测访问者是iphone,android,web(摘录)

aps.net 可以使用WebFormViewEngine来实现。 参考文章:http://www.hanselman.com/blog/MixMobileWebSitesWithASPNETMVCAndTheMobileBrowserDefinitionFile.aspx 源代码 C#代码 public class MobileCapableWebFormViewEngine : WebFormViewEngine { public…

买的情侣裤衩寄前男友家了,怎么办?

1 那你是要和别人一起去吗!▼2 我马上想到我一老师了!(素材来源网络,侵删)▼3 当代父母对孩子的期望变化(素材来源网络,侵删)▼4 这个小象打破我的观念?▼5 小个子买…

ctf php sql注入,CTF—攻防练习之HTTP—SQL注入(SSI注入)

主机:192.168.32.152靶机:192.168.32.161ssI是赋予html静态页面的动态效果,通过ssi执行命令,返回对应的结果,若在网站目录中发现了.stm .shtm .shtml等,且对应SSL输入没有过滤该网站可能存在SSI注入漏洞ssi…

OAuth 2.1 带来了哪些变化

OAuth 2.1 是 OAuth 2.0 的下一个版本, OAuth 2.1 根据最佳安全实践(BCP), 目前是第18个版本,对 OAuth 2.0 协议进行整合和精简, 移除不安全的授权流程, 并发布了 OAuth 2.1 规范草案, 下面列出了和 OAuth 2.0 相比的主要区别。⚡ 推荐使用 Authorization Code PKC…

54个站在人类智商巅峰的男人!告诉你2400年的物理学史里都有什么……

全世界只有3.14 % 的人关注了爆炸吧知识一沙见世界 一花窥天堂手心握无限 须臾纳永恒杨振宁曾说读上面的四句诗可以感受到物理的美但物理的美不至于此物理还有一种庄严美一种神秘美一种初窥宇宙奥秘的畏惧美物理就是如此的迷人任何语言在它的面前都很贫瘠数学让人摆脱了愚昧而…