d3.js笔记
一般的图形都是有SVG的path元素构成的,每张图都有不同的path元素,每个path元素都有d属性来定义path,如
下面大概简单介绍下不同d3 shape的路径生成器
Line generator
我们给d3一个(x,y)坐标的数组,d3就能生成一串path data string。我们来定义一个做标数组:
var points = [[0,80],[100,100],[200,30],[300,50],[400,40],[500,80]]
lineGenerator的任务就是接收一个坐标数组,输出一个path data string直接可以作为path元素的d属性值。
我们首先声明一个line generator:
var lineGenerator = d3.line(); var pathData = lineGenerator(points); // pathData is "M0,80L100,100L200,30L300,50L400,40L500,80" d3.select('path') .attr('d',pathData)
对于line generator函数,我们可以有以下可以配置
- .x() and .y() accessor functions
默认情况下每一个数组元素都代表了一个2纬的数组,比如[0,100],然而我们也可以告诉line generator来如何解读传入的数据,而这就要使用对应的accessor functions了:.x()和.y().例如假设我们有以下对象的数组:
var data = [{value:10},{value:50},{value:30},{value:40},{value:20},{value:70},{value:50}]
我们就可以这样来定义accessor函数:
lineGenerator .x(function(d,i){ return xScale(i); }) .y(function(d){ return yScale(d.value); })
在这个例子中,我们使用数组的index来定义x,(注意我们同时使用了比例尺函数)
- .defined() (to handle missing data)
var points = [[0,80],[100,100],null,[300,50],[400,40],[500,80]]
我们告知line generator 每一个坐标只有是non-null时才是有效的,通过下面的代码
lineGenerator .defined(function(d){ return d !== null })
当我们再次调用lineGenerator并渲染后就得到一个有着断断续续的line
- .curve (to specify how the points are interpolated) and
我们也可以定义这个path的points之间是如何插值的。比如,我们可以使用一个B-spline算来来插值:
var lineGenerator = d3.line() .curve(d3.curveCardinal)
虽然有相当多的不同类型的curve type在d3中可以使用,但是我们也可以把这些插值类型简单分为两类:一种是必须经过指定points的类型(比如:curveLinear,curveCardinal,curveCatmullRom,curveMonotone,curveNatural,curveStep),另一种是不必经过每一个points(比如curveBasics和curveBundle)
- .context() to render to a canvas element.
默认情况下shape generator输出SVG path data.然而我们也可以通过.context()函数来指定使用canvas来绘图:
var context = d3.select('canvas').node().getContext('2d') lineGenerator.context(context) context.strokeStyle = '#999' context.beginPath(); lineGenerator(points); context.stroke()
还有一种特殊情况
radial line generator和普通的line generator是类似的,唯一的不同是该generator对坐标的解读是“极坐标系”(从12点开始顺时针运行的)角度和半径,而不是x,y坐标::
类似于lineGenerator,对应的accessor function .angle()和.radius()如下:
Area generator
区域生成器输出一个通过两条lines来定义的一个区域的path data来工作的。默认情况下,它在y=0的水平线和一个由一个点数组来定义的多段线线之间生成一个区域:
我们可以通过.y0() accessor函数来定义这个base line:
就变成了如下的图形:(通常情况下我们使用图形的height作为base line)
我们也可以给.y0() accessor函数一个函数来指明如何获取y0的值,类似于.y1() accessor
典型地,.y0()定义了base line, .y1()定义了top line. 注意我们也使用了.x()定义了x坐标(base line和top line使用的是相同的x坐标哦!!)
和line generator一样,我们可以指定在点之间是如何插值的(.curve()),以及如何处理missing data(.defined())以及如何在canvas而不是在svg中渲染(.context())
还有一种特殊情况
radial area generator和area generator是类似的,唯一的不同是这些点我们是使用angle角度(从12点顺时针开始的角度)和半径radius来定义的,而不是x和y来定义的:
Stack generator
stack generator接收一个multi-series data而对每一个series来生成一个数组,而每个数组包含着各data point的lower和upper values
lower和upper values被用于计算位置这样每个series都堆叠在前一个series上面
.keys()配置函数定义了在stack generation中哪些series被包含其中。
.order()
.offset()
Arc generator
arc generator用于从angle和radius值来产生path data.下面创建一个arc
随后可以给该generator传入一个包含着startAngle, endAngle,innerRadius,outerRadius属性值的对象来生成path data
我们可以使用innerRadius,outerRadius,startAngle,endAngle函数来配置,而不用每次生成arc generator时传入对象参数:
我们也可以配置corner radius(corner Radius)以及弧线段之间的padding值(padAngle,padRadius)
Arc padding有两个参数:padAngle和padRadius他们合在一起定义了两个相邻弧段之间的距离。这样在上面的例子中,padding distance就是0.02*100=2.注意padding计算时会尽可能地保持(如果可能的话)弧段之间的边界保持平行。
我们也可以为startAngle, endAngle, innerRadius,outerRadius来定义对应的accessor functions
Centroid
有时,计算弧线的中心点是很有用的,比如当我们要放置label时,往往希望放到中心点附件,d3给我们提供了一个.centroid()函数来实现
Pie generator
pie generator和弧线generator是类似的。给pie generator一个数据数组,pie generator就会输出一个反映了原始start和end angles数据的对象数
随后,我们可以使用一个arc generator来创建对应的path strings
注意pieGenerator的输出包含了startAngle和endAngle两个属性。这些正好是arcGenerator所需要的输入!
实际上pieGenerator是一个layout了,而不是路径生成器!pie generator包含了一系列的配置函数,包括:.padAngle(),.startAngle(),.endAngle(),.sort(),.padAngle()定义了一个在相邻段之间的angular padding
.startAngle()
and .endAngle()
配置pie chart的startAngle和endAngle. 这将允许创建半圆形的pie charts:
默认情况下段的起始和结束角度使得段之间以降序排列。然而我们可以更改这种排序方式,方法是使用.sort()函数:
Symbols generator
symbol generator用于产生在可视化领域中常用的symbol的path data:
D3包含了下面的symbol types:
this.xAsis = vm.data
.map((d) => {
return {
name: new Date(d.day),
}
}); <g class="xAsis" v-for="(item,index) in xAsis">
<rect width="2"
height="15"
:y="item.x - 15"
text-anchor="end"
fill="#49A3AE">{{item.name}}</rect>
</g>