关于贝塞尔曲线的一些事

© Young 2017-07-21 20:22
Welcome to My GitHub

概述

前段时间用SVG实现了一个简单的路径过渡动画,如下:

由于以前很少接触SVG导致遇到了一些困难,解决之后得到了一些总结:

其一:路径过渡动画只适用于指令类似的路径;

上述图中分别是动画前路径和动画后路径,由于这两个路径是设计同学分开设计的,两个路径之间指令完全不一样,比如动画前路径中全是贝塞尔曲线,但是动画后路径中却存在直线;因此这两个路径之间是不能在没有任何处理的情况下通过Animation实现过渡动画效果的。

其二:Animation在IPhone中存在兼容性问题;

在IPhone中一个路径存在多个Animation时多次触发会有bug,某些Animation不能显式的表现出来;

问题例子

解决方案

实现之后喜闻乐见加需求了,产品要求图形张开之后里边的文案是可配置的,也就是说图形张开之后水平区域的宽度是可控制的;面对这种情况我唯一能想到的就只有通过JS动态更改路径中的指令参数了,而这就要求我得完全明白路径中指令和参数代表的是什么意思了!

SVG缩写

不幸的是软件导出的SVG文件出于文件大小的考虑会采用缩写的形式,导致可读性较差,比如:

<path d="M640.5,300.5c-36,0-221.2-0.1-235.5-0.1c-18.5,0-29.6-15.9-29.5-30.7c0-14,12.3-29.9,29.5-29.9c13.9,0,198.2,0,235.4,0L640.5,300.5z"/>

不仅没有空格分隔符,还有很多不明意义的横杠(后来才知道其实就是负号的意思);

通过查询资料发现PATH属性存在一些缩写规则,比如:

字母和数字之间可以省略分隔符;
负数和数字之间可以省略分隔符;
数字和字母之间也可以省略分隔符;
逗号就是普通的分隔符和空格类似,之所以使用逗号代替空格应该是因为空格在不同操作系统或者不同编码格式下会有差异;

因此上述软件导出的PATH其实和下边格式化之后的PATH表现一致。

<path d="M640.5, 300.5 c -36, 0 -221.2 -0.1 -235.5 -0.1 c -18.5, 0 -29.6 -15.9 -29.5 -30.7 c 0 -14, 12.3 -29.9, 29.5 -29.9 c 13.9, 0, 198.2, 0, 235.4, 0 L640.5,300.5z"/>

相对坐标

格式化之后可读性好了很多,但是还有一个地方比较困惑,SVG中大写C和小写c都表示三次贝塞尔曲线,但是大写C中的坐标是绝对坐标,小写c中的坐标是相对坐标;三次贝塞尔曲线存在一个起始点、一个结束点和两个控制点,那么相对坐标中是都是相对起始点而言还是相对上一个点而言呢?

稍作验证即可得出相对坐标都是相对起始点而言的,起始点也就是上一个指令的结束点;

示例代码

其实大家可以稍微思考下为什么软件导出的会默认是相对坐标?以及为什么相对坐标都是相对上一个指令的结束点而言?
猜想:相对坐标会减少文件字符从而减少文件大小,另外相对上一个指令的结束点和相对当前指令的上一个点的区别在于前一种方式一个指令中的数据是不存在联系的,而后一种方式一个指令中的数据是存在的联系的,也许这种联系会带来逻辑上的复杂性(比如会影响绘制效率等)。
当然上述猜想也可能是我想多了……

贝塞尔曲线

贝塞尔曲线的数学基础是早在1912年就广为人知的伯恩斯坦多项式。但直到1959年,当时就职于雪铁龙的法国数学家Paul de Casteljau才开始对它进行图形化应用的尝试,并提出了一种数值稳定的de Casteljau 算法。然而贝塞尔曲线的得名,却是由于1962年另一位就职于雷诺的法国工程师Pierre Bézier 的广泛宣传,他使用这种只需要很少的控制点就能够生成复杂平滑曲线的方法,来辅助汽车车体的工业设计。

正是因为控制简便却具有极强的描述能力,贝塞尔曲线在工业设计领域和计算机图形学领域得到了广泛的应用,贝塞尔曲线根据控制点的多少分为,一次贝塞尔曲线、二次贝塞尔曲线、三次贝塞尔曲线等。

手绘二次贝塞尔曲线

在坐标系中选取三个不共线的点,分别是P0P1P2
在线段P0P1上任选一点Q0,并计算线段P0Q0P0P1上所占的比例t
根据上一步得到的比例,在线段P1P2上找到Q1,使得P1Q1P1P2上所占的比例等于t
连接Q0Q1
在新线段上再次找到B,使得Q0BQ0Q1上所占比例等于t
B即为该二次贝塞尔曲线上的一点;
以此类推。

根据上述规律可以对二次贝塞尔曲线公式进行推导;

完成产品要求

了解了这么多没什么卵用的东西,是时候解决产品的要求了;

具体代码

最终结果如图:

发表评论

电子邮件地址不会被公开。 必填项已用*标注