初识SVG

最近遇到一个关于彩票中奖号码展示的项目,里面有很多技术难点,其中一个就是把各开奖号码之间用线段连接起来,这是一个典型网页图形绘制问题。本文尝试讲解如何利用SVG技术实现折线图形的绘制。

我们知道,在网页中绘制图形有很多种方式,如canvas、svg、vml等都可以绘制优秀的矢量图形。关于它们的区别和适用性比较,可以参考这篇文章,本文只介绍如何使用SVG的基础知识实现我的工作目的。

首先分析下问题和解决方案

彩票号码一般都显示为圆形的小球,上面叠加一个阿拉伯数字。要把一系列小球用直线连接,需要知道每个小球的位置信息,然后用SVG的line方法画出来。

那么问题来了,我们怎么才能得到小球的位置信息呢?

一般计算机的坐标系都是以左上角为原点,横向为X轴,纵向为Y轴。SVG坐标系也不例外。

此外,我们把小球都放表格中,并规定好单元格的宽高。以表格的左上角为原点,就能轻松得到每个单元格的XY轴信息,进而得到圆心的坐标。very nice!

初识SVG_第1张图片
svg坐标系

但实际上我们只得到圆心的坐标是不行的,因为SVG层叠加在表格上面,如果用Line方法把各个圆心连接起来,会把小球上面的文字盖住。所以Line的起止坐标必须在小球的边缘上。而且,除了第一个和最后一个小球外,每个小球都要有一个画入点和一个画出点,分别指向它的上一个小球和下一个小球。

那么问题又来了,怎样才能得到这些出入点的坐标呢?

思前想后,终于把这个问题抽象为一道数学题:已知一个圆的圆心坐标和半径,有一条从圆心发出的直线,假设直线与X轴的夹角为a,求该直线与圆相交的点的坐标。

Oh My Dog!这特么解析几何啊!哥中学课本早烧香了,咋办?
zzz...


没办法,自己画吧。在纸上算啊算,电脑上测啊测,终于憋出一个公式!

初识SVG_第2张图片
想要草稿纸的自行来取

写成函数如下:

function calcPointCoor(cx,cy,r,alpha){
//cx,cy: coordination of the circle
//r: radius
//alpha: angle of line and X axis
return {x:cx + r * Math.cos(alpha),y:cy + r * Math.sin(alpha)};
}

其中cx,cy是圆心坐标,r是半径,alpha为角度。

然而如何计算两个小球之间的角度呢?

还解析几何啊!想到脑细胞会烧坏一坨,还是算了。我考虑用Snap SVG组件的angle方法来做,这个方法只要两个点的x,y坐标,就能返回他们之间的夹角。

要注意的是,给angle方法传入的参数顺序不同,得出的角度会有差别。经过测试,angle方法得出的角度值是自X轴正向顺时针增加的。这样,如果要按解析几何平面坐标系来计算的话,就需要加入或减去一个π周期来修正。

另外,还需要把角度值转换为弧度值。因为JS中Math对象的正余弦函数只接受弧度值。

经过上帝测试,最终得出以下方法:


//radius , coordinations of current cicle and next circle
var r,cur_cx,cur_cy,next_cx,next_cy;

//.....

var ang = Snap.angle(next_cx,next_cy,cur_cx,cur_cy) * Math.PI / 180;

var coor1 = calcPointCoor(cur_cx,cur_cy,r, ang);

var coor2 = calcPointCoor(next_cx,next_cy,r, ang + Math.PI);

var c = svg.path("M" + coor1.x + " " + coor1.y + "L" + coor2.x + " " + coor2.y).attr({stroke:stroke_color,strokeWidth:1.5});

这里面的coor1是当前小球到下一个小球的画出点坐标,coor2是下一个小球的画入点坐标。

再往下就简单了,SVG中有Line方法,只要循环一下某一组中所有中奖号码的小球圆心坐标,就可以搞定一切。

但实际应用中,Path方法比Line方法更高效。因为画一段线条就得用一个Line,而Path方法只要给出d属性的M和L值,就可以在一个标签中实现N段线条,然后你就能方便地切换显示了。哈哈!

初识SVG_第3张图片
svg实现折线

总结:

  • SVG可以像使用其他HTML标签一样来灵活生成,不管你是用PHP还是JavaScript。
  • 对CSS有效的标签同样适用于SVG标签。
  • 能用组件或库的尽量用,否则死很多脑细胞

文中涉及的技术和组件哥也是现学现卖,欢迎批评指正。

你可能感兴趣的:(初识SVG)