Learning D3.js d3的path讲解
转帖: http://jsbin.com/omajal/23/edit?html,output
svg的path标签被称为”可以组成任何形状的形状”
SVG Path可以绘制任何形状的图形,包括矩形,圆形,椭圆,折线,多边形,直线,曲线等。
W3 标准对SVG 的Path定义如下
SVG路径代表一个形状的轮廓,可以描边,填充,用作剪切路径,或任何三者的结合。
W3提供了一个形象的比喻,用钢笔和纸来表示svg的path
* 想象一个钢笔放在一张纸上。
* 钢笔在某点与纸接触。
* 笔尖移动到另一处。
* 这两个点之间的路径可以是直线或曲线。
* 曲线可以是一个弧,一立方曲线或二次贝塞尔曲线。
这意味着我们可以使用SVG路径做出任何类型的SVG形状。
SVG Path的例子
SVG Path元素的形状被一个属性所定义:d.(这也是为什么上一篇教程 通过设置d就可以绘制出一个圆环)
d这个属性,包含一系列的方法与参数.因此我们可以把这个属性称作一个“微语言”
这些方法与参数其实就是告诉电脑”如何在纸上移动你的钢笔”.
下面我们会介绍一些经典的写法,包含moveto(设置一个起点),lineto(画一条直线),curveto(画一个曲线用三次贝塞尔曲线),arc(椭圆或圆弧)和closepath(闭合路径)。
首先我们可以绘制一个三角形
- M 10 25 – 把笔落下,放在10,25处
- L 10 75 – 从起点10 25出发绘制一条直线到10 75处
- L 60 75 – 从起点10 75出发绘制一条直线到60 75处
- L 10 25 – 从起点60 75出发绘制一条直线到10 25处
注意! (M, L)是大写的,表示绝对位置。当使用相对位置时,要小写。
SVG Path 微语言
到底如何去描述path呢,参考下面:
命令 | 参数 | 是否能重复 | 解释
M ( m ) | x, y | 不能 | 把笔尖移动到新位置,但因为没有落笔,不会“描绘图形”。所有的path都需要以m/M开头
L ( l ) | x, y | 能 | 从当前点画一条直线到坐标x,y
H ( h )| x|能 |画水平线,从当前点画一条水平线,到横坐标为X处
V ( v )| y |能|画垂线,从当前点画一条垂线,到纵坐标为Y处
C ( c ) | x1 y1 x2 y2 x y| 能 | 绘制一条曲线。起点为当前点,终点为x,y.使用(x1,y1)作为开始阶段曲线的控制点,使用 (x2,y2)作为结束阶段的控制点
S ( s ) | x2 y2 x y |能| 绘制一条平滑的曲线。 绘制一条以当前点为起点,x,y为终点绘制一条三次方贝塞尔曲线。注意这是一个简写,这条曲线同样也有两个控制点,但此时x1 y1跟x2,y2是对称的,可以直接写x2y2这一个。
Q ( q ) | x1 y1 x y |能 |二次方贝塞尔曲线。绘制一条以当前点为起点,x,y为终点的二次方贝塞尔曲线。x1 y1为控制点
T ( t ) | x y| 能 |绘制二次方贝塞尔曲线的简写。绘制一条以当前点为起点,x,y为终点的二次方贝塞尔曲线。控制点假定为前一个命令的控制点相对于当前点的反射。 如果前一个命令不存在,或者前一个命令不是二次贝塞尔曲线命令或平滑的二次贝塞尔曲线命令,则此控制点就是当前点。
A ( a ) | rx ry x-axis-rotation large-arc-flag sweep-flag x y | 能|椭圆弧线命令在当前点与指定的终点 (x, y)之间创建一条椭圆弧线。
Z ( z ) |none |不能|闭合路径。会有一条线连接路径最后一个点与起点。
关于椭圆的参数,我用拉斐尔做了个简单的demo大家可以看下就懂了 http://jsbin.com/omajal/23/edit
另外提供两张二次贝塞尔曲线与三次贝塞尔曲线的原理图
D3.js Path 的例子
D3.js 包含了很多方便的方法来创建path,在浏览这些方法之前,我们先看一个简单的例子,利用d3js画线。
通常在一条折线中,包含很多的x,y点,这些点两两组合就会变成折线。
比如这样的数据
1
2
|
<code>[{"x":1, "y":5}, {"x":20, "y":20},{"x":40, "y":10},{"x":60, "y":40},{"x":80, "y":5}, {"x":100,"y":60}];
</code>
|
这里我们需要一个函数,把这些xy点翻译成上面讲解的path“微语言”
1
2
|
<code>d3.svg.line()
</code>
|
这个path数据生成器函数可以使用我们的数据来创造一条path。在使用前,我们需要告诉d3js如何去获取数据中的x,y坐标。
因此我们创建一个函数,这个函数可以方便的去拿到数据中的x,y坐标。
上面的函数可以把data数组中的x,y数据提取出来。之后呢,通过interpolate的设置,会使用线,连接每个点。之后就会返回一条path了。
让我们看看完整的例子
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
<code>//数据
var lineData=[{"x":1, "y":5}, {"x":20, "y":20},
{"x":40, "y":10},{"x":60, "y":40},
{"x":80, "y":5}, {"x":100,"y":60}];
//线生成器
var lineFunction = d3.svg.line()
.x(function(d){returnd.x;})
.y(function(d){returnd.y;})
.interpolate("linear");
//svg容器
var svgContainer = d3.select("body").append("svg")
.attr("width",200)
.attr("height",200);
//把path扔到容器中-- lineData和lineFunction,并给d赋属性
var lineGraph = svgContainer.append("path")
.attr("d",lineFunction(lineData))
.attr("stroke","blue")
.attr("stroke-width",2)
.attr("fill","none");
</code>
|
然后我们就拿到这么一张图:
.attr(“d”, lineFunction(lineData)) 是一个很关键的语句。这里我们把数据传给了lineFunction,返回了path的“微语言”,之后给d属性赋值,
这里我们直接使用了.append(“path”),因为我们只需要根据现有的数据生成一条折线。
还记得第一篇教程讲解的selectAll(), .enter(), append()组合么,那是针对多组数据来做的。而上面不需要判断有多少组数据,然后划分多少空间,放入图形啥的。
.interpolate(“linear”)这个函数告诉d3js使用直线来连接点。
D3.js提供了11种不同的线,可以让d3.svg.line() 函数来操纵.这里有非常多的专业名词,我觉得翻译还不如不翻译。。给大家看看吧。。
- linear – piecewise linear segments, as in a polyline.
- step-before – alternate between vertical and horizontal segments, as in a step function.
- step-after – alternate between horizontal and vertical segments, as in a step function.
- basis – a B-spline, with control point duplication on the ends.
-
d3.svg.line()这类path生成器,既是一个函数也是一个对象,这意味着你可以把他作为方法来生成path,也可以用一些额外方法去改变它自身的属性。
并且他也是支持 链式调用的
类似d3.svg.line()这样的path生成器还有很多。比如- d3.svg.line – 线path生成器
- d3.svg.line.radial – 径向path
- d3.svg.area – 区域path
- d3.svg.area.radial – 径向区域path
- d3.svg.arc -圆与圆弧path
- d3.svg.symbol – 符号path
- d3.svg.chord -chord path,也是我们这一系列教程要用到的东西!
- d3.svg.diagonal – diagonal path
- d3.svg.diagonal.radial – diagonal radial path
这些生成器在d3js驱动下都拥有读取跟写入的方法, 因此可以非常方便的生成各种path。