贝赛尔曲线绘制趋势图

在许多网页应用中,经常会使用SVG来绘制趋势图、饼图等,很多的地图交互应用中,也会使用SVG来绘制地图区域,达到用户信息交互的效果。本文以趋势图为例,说明在使用path元素绘制曲线图时可能会使用的不同方式。

假设要用于制作趋势图的数据如下表。

月份产值月份产值月份产值

1 用折线画趋势图

用折线画趋势图是最为简单的一种方式,直接将各端点按顺序连接起来就可以了。这样做其实没什么毛病,朴实无华,但最为实用。要说缺点,那就是太简单,不能体现程序员的技术功底。

2 用贝塞尔曲线画趋势图(水平控制点)

用贝塞尔曲线来画趋势图,最简单的一种方法,就是设置水平控制点。也就是每一个端点与对应的控制点y轴坐标相同,x轴坐标按一定比例r进行偏移,r指控制点的x坐标与端点x坐标的距离和相邻两个端点距离的比例。当r越大,端点附近的线越平滑,r越小,线越尖锐。当r等于0时,贝塞尔曲线与折线图一致。当r过大时,会出现曲线往回弯的情况,不符合曲线图的特性,一般r应小于0.5较为合适。

(以下三个曲线图中r均为0.3)

3 参考前后变化趋势设置控制点

用水平控制点,基本可以满足使趋势图变得圆滑的要求。但会有一个缺点,就是每两个端点的连线,都是一段S形的连线。因此,在我们的例子中,5~8月是等差变化,这种情况下,水平控制点的缺点就尤为明显,因为在这种情况下,我们一般认为这里应该是一段往上走的直线。因此,可以使用第三种绘制曲线的方式,即参考前后端点变化趋势来设置控制点。

每一个端点在设置控制点时,依照前后两个端点的y坐标的差值来进行等比例调整,如:端点p的控制点的y坐标偏移量=(端点(p+1)的控制点的y坐标-端点(p-1)的控制点的y坐标)*r/2。第一个和最后一个端点则根据相领端点的y坐标进行调整即可。这样处理后,整个曲线会显得更加附合变化趋势且丝滑。

4 在参考前后变化趋势的情况下保证极值点

参考前后两个端点的变化情况来设置控制点,会出现一个问题,就是曲线中的y坐标会超过或低于数据中的极值点。虽然从数学的角度上来看,预测的图形绘制与数据变化情况并不冲突,但一般情况下,我们还是习惯于把现有的数据当成是整体变化的极值,因此,需要对这一情况进行处理。

需要进行修正的控制点有两种。第一,处于波峰或波谷的数据,也就是前后两个端点的y坐标都大于或小于当前端点,这时候,当前端点采用水平控制点的方式来设置前后两个控制点。第二,当前端点的y坐标大于后一端点,但相应控制点的y坐标大小却相反,反过来也一样,这时候,当前端点也需要采用水平控制点的方式来设置前后两个控制点。

通过这样的处理过后,基本满足了我们对于趋势曲线的要求,虽然看起来不是没那么完美,但也够用了。

用贝塞尔曲线来绘制趋势图是常用的一种方式,但由于曲线有预估的成分存在,所以绘制出来的图形并不一定符合实际情况。数据变化情况还有很多,也可以有更多的处理办法,还是要看实际的需求来进行计算和实现。