d3-shape
可视化通常由离散图形标记组成, 比如 symbols, arcs, lines 和 areas。虽然条形的矩形可以很容易的使用 SVG 或者 Canvas 来生成, 但是其他的比如圆形的扇形以及向心 Catmull-Rom
样条曲线就很复杂。这个模块提供了许多图形生成器以便使用。
与 D3
的其他特性一样,这些图形也是又数据驱动的: 每个图形生成器都暴露了一个如何将数据映射到可视化表现的访问器。例如你可以通过 scaling 定义一个时间序列的线条生成器以生成图表:
var line = d3.line()
.x(function(d) { return x(d.date); })
.y(function(d) { return y(d.value); });
线条生成器可以计算 SVG
path
元素的 d
属性:
path.datum(data).attr("d", line);
或者也可以将其渲染到 Canvas 2D
上下文中:
line.context(context)(data);
更多信息参考 Introducing d3-shape.
Installing
NPM
安装: npm install d3-shape
. 也可以下载 latest release. 此外还可以从 d3js.org 以 standalone library 或作为 D3 4.0 的一部分载入. 支持 AMD
, CommonJS
以及基本的标签引入形式,如果使用标签引入则会暴露全局 d3
变量:
<script src="https://d3js.org/d3-path.v1.min.js"></script>
<script src="https://d3js.org/d3-shape.v1.min.js"></script>
<script>
var line = d3.line();
</script>
API Reference
- Arcs
arc
生成器用来在饼图或圆环图中生成 circular(圆形) 或 annular(环形) 扇形。如果 start 和 end 之间的角度(angular span)差大于 τ 则arc
生成器将会产生一个完整的圆或环。如果小于τ
则生成的扇形可能有 rounded corners(圆角) 和 angular padding(角度间隙)。弧的中心总是在 ⟨0,0⟩; 可以使用transform
(参考 SVG, Canvas) 来将其移动到指定的位置。可以与 pie generator 对比,
pie
生成器用来计算一组数据作为饼图或圆环图时所需要的角度信息;这些角度信息会被传递给arc
生成器生成图形。d3.arc() <源码>
使用默认的设置创建一个新的
arc
生成器。arc(arguments…) <源码>
根据指定的 arguments 生成
arc
。arguments 是任意的; 它们只是简单地传递到arc
生成器的访问器函数的对象。例如,根据默认的设置,传入的对象应该包含以下半径和角度信息:var arc = d3.arc(); arc({ innerRadius: 0, outerRadius: 100, startAngle: 0, endAngle: Math.PI / 2 }); // "M0,-100A100,100,0,0,1,100,0L0,0Z"
如果半径和角度信息在构建生成器时已经被设置为常量,则不需要传入任何参数:
var arc = d3.arc() .innerRadius(0) .outerRadius(100) .startAngle(0) .endAngle(Math.PI / 2); arc(); // "M0,-100A100,100,0,0,1,100,0L0,0Z"
如果
arc
生成器拥有 context 则这个弧会被作为 path method 的调用序列渲染到对应的上下文中并返回空。否则,返回一个 path data 字符串。arc.centroid(arguments…) <源码>
计算由给定 arguments 生成的 generated的中间点 [x, y]. arguments 是任意的,它们会被传递给
arc
生成器的访问器。为了与生成的弧保持一致,访问器必须是确定的。例如,相同的参数返回相同的值。中间点被定义为 (startAngle + endAngle) / 2 和 (innerRadius + outerRadius) / 2。例如:注意,中间点 并不是几何中心,因为几何中心点可能位于弧之外; 这个方法可以用来方便的对
labels
进行定位。arc.innerRadius([radius]) <源码>
如果指定了 radius 则将内半径设置为指定的函数或数值并返回当前
arc
生成器。如果没有指定 radius 则返回当前的内半径访问器,默认为:function innerRadius(d) { return d.innerRadius; }
将内半径设置为函数在生成堆叠的极坐标条形图时非常有用,通常与 sqrt scale 组合。更常见的是将内半径设置为常量用来生成
donut
或者pie
图。如果外半径小于内半径则内外半径将会被互换。负值被看做0
。arc.outerRadius([radius]) <源码>
如果指定了 radius 则将外半径设置为指定的函数或数值并返回当前
arc
生成器。如果没有指定 radius 则返回当前的外半径访问器,默认为:function outerRadius(d) { return d.outerRadius; }
将内半径设置为函数在生成
coxcomb
图或极坐标条形图时非常有用,通常与 sqrt scale 组合。更常见的是将外半径设置为常量用来生成donut
或者pie
图。如果外半径小于内半径则内外半径将会被互换。负值被看做0
。arc.cornerRadius([radius]) <源码>
如果指定了 radius 则将拐角半径设置为指定的函数或数值并返回当前
arc
生成器。如果没有指定 radius 则返回当前的拐角半径访问器,默认为:function cornerRadius() { return 0; }
如果拐角半径大于
0
则弧度的拐角将会适用指定半径大小的圆进行圆滑。对于扇形,会有两个拐角被圆滑处理,对于环形,所有的四个拐角都会被圆滑处理。拐角处理示意图如下:拐角半径不应该大于 (outerRadius - innerRadius) / 2。此外,对于弧长小于等于
π
的弧, 当两个相邻的拐角角相交时,拐角半径可以减小。这种情况更经常发生在内角。参考 arc corners animation 中的插图。arc.startAngle([angle]) <源码>
如果指定了 angle 则将起始角度设置为指定的函数或数值并返回当前
arc
生成器。如果没有指定 angle 则返回当前的起始角度访问器,默认为:function startAngle(d) { return d.startAngle; }
angle 以弧度的形式指定,
0
表示12
点钟方向并且顺时针方向为正。如果 |endAngle
-startAngle
| ≥τ
则会绘制一个完整的扇形或圆环。arc.endAngle([angle]) <源码>
如果指定了 angle 则将终止角度设置为指定的函数或数值并返回当前
arc
生成器。如果没有指定 angle 则返回当前的终止角度访问器,默认为:function endAngle(d) { return d.endAngle; }
angle 以弧度的形式指定,
0
表示12
点钟方向并且顺时针方向为正。如果 |endAngle
-startAngle
| ≥τ
则会绘制一个完整的扇形或圆环。arc.padAngle([angle]) <源码>
如果指定了 angle 则将间隙角度设置为指定的函数或数值,并返回当前
arc
生成器。如果 angle 没有指定则返回当前间隙角度访问器,默认为:function padAngle() { return d && d.padAngle; }
间隔角度会转换为一个在两个相邻的弧之间的确定的线性距离,定义为 Pies
pie
生成器不会直接生成图形,但是会计算生成饼图或环形图所需要的角度信息,这些角度信息可以被传递给 arc generator。d3.pie() <源码>
构建一个新的使用默认配置的
pie
生成器。pie(data[, arguments…]) <源码>
根据指定的 data 数组生成一组对象数组,其中每个对象包含每个传入的数据经过计算后的角度信息。可以包含其他的额外 argements,这些额外的参数会直接被传递给当前数据计算后生成的对象或饼图生成器的访问器。返回数组的长度与 data 长度一致,其中第 i 个元素与输入数据中的第 i 个元素对应。返回数组中的每个对象包含以下属性:
data
- 输入数据; 对应输入数组中的数据元素.value
-arc
对应的 value.index
-arc
基于0
的 sorted index(排序后的索引).startAngle
-arc
的 start angle.endAngle
-arc
的 end angle.padAngle
-arc
的 pad angle.
这种形式的设计可以兼容
arc
生成器的默认 startAngle, endAngle 和 padAngle 访问器。角度单位是任意的,但是如果你想将饼图生成器和arc
生成器结合使用,则应该以弧度的形式指定角度值,其中12
点钟方向为0
度并且顺时针方向为正。给定一个小数据集,下面为如何计算其每个数据的角度信息:
var data = [1, 1, 2, 3, 5, 8, 13, 21]; var arcs = d3.pie()(data);
pie()
constructs(构造) 一个默认的pie
生成器。pie()(data)
为指定的数据集 invokes(调用) 饼图生成器,返回一组对象数组:[ {"data": 1, "value": 1, "index": 6, "startAngle": 6.050474740247008, "endAngle": 6.166830023713296, "padAngle": 0}, {"data": 1, "value": 1, "index": 7, "startAngle": 6.166830023713296, "endAngle": 6.283185307179584, "padAngle": 0}, {"data": 2, "value": 2, "index": 5, "startAngle": 5.817764173314431, "endAngle": 6.050474740247008, "padAngle": 0}, {"data": 3, "value": 3, "index": 4, "startAngle": 5.468698322915565, "endAngle": 5.817764173314431, "padAngle": 0}, {"data": 5, "value": 5, "index": 3, "startAngle": 4.886921905584122, "endAngle": 5.468698322915565, "padAngle": 0}, {"data": 8, "value": 8, "index": 2, "startAngle": 3.956079637853813, "endAngle": 4.886921905584122, "padAngle": 0}, {"data": 13, "value": 13, "index": 1, "startAngle": 2.443460952792061, "endAngle": 3.956079637853813, "padAngle": 0}, {"data": 21, "value": 21, "index": 0, "startAngle": 0.000000000000000, "endAngle": 2.443460952792061, "padAngle": 0} ]
需要注意的是,返回的数组与传入的数据集的次序是一致的,无论数据元素的值大小。
pie.value([value]) <源码>
如果指定了 value 则设置当前饼图生成器的值访问器为指定的函数或数值,并返回当前饼图生成器。如果没有指定 value 则返回当前的值访问器默认为:
function value(d) { return d; }
当生成饼图时,值访问器会为传入的数据的每个元素调用并传递当前数据元素 d, 索引
i
以及当前数组data
三个参数。默认的值访问器假设传入的数据每个元素为数值类型,或者可以使用 valueOf 转为数值类型的值。如果你的数据不是简单的数值,你应该指定一个返回数值类型的值访问器。例如:var data = [ {"number": 4, "name": "Locke"}, {"number": 8, "name": "Reyes"}, {"number": 15, "name": "Ford"}, {"number": 16, "name": "Jarrah"}, {"number": 23, "name": "Shephard"}, {"number": 42, "name": "Kwon"} ]; var arcs = d3.pie() .value(function(d) { return d.number; }) (data);
这与 mapping 类似,在调用饼图生成器之前,对数据进行预处理:
var arcs = d3.pie()(data.map(function(d) { return d.number; }));
访问器的好处是输入数据仍然与返回的对象相关联,从而使访问数据的其他字段变得更容易,例如设置颜色或添加文本标签。
pie.sort([compare]) <源码>
如果指定了 compare 则将数据比较函数设置为指定的函数并返回饼图生成器。如果没有指定 compare 则返回当前的数据对比函数,默认为
null
。如果数据比较函数和值比较函数都为null
则返回的arc
会保持数据的次序。否则,返回的结果会安装相应的比较函数进行排序。设置数据对比函数默认会将 value comparator(值比较函数) 设置为null
。compare 函数会传递两个参数 a 和 b, 每个元素都来自输入数据。如果数据 a 对应的扇形在 b 前面,则比较函数应该返回小于
0
的值; 如果 a 对应的扇形在 b 的后面则比较函数应返回大于0
的值;返回0
表示 a 和 b 的相对位置不做任何调整。例如根据name
对生成的扇形数组进行排序:pie.sort(function(a, b) { return a.name.localeCompare(b.name); });
排序操作不会影响 generated arc array(生成的数组次序), 生成的数据次序与传入的数组次序保持一致。排序操作是通过修改每个生成的元素的起始角度值来实现排序的。
pie.sortValues([compare]) <源码>
如果指定了 compare 则将
value
比较函数设置为指定的函数并返回当前的饼图生成器。如果没有指定 compare 则返回当前的值比较函数,默认为降序。默认的值比较函数实现形式为:function compare(a, b) { return b - a; }
如果数据比较函数和值比较函数都为
null
则生成的数组次序与输入数据的次序保持一致。否则,数据会按照数据比较函数进行排序。设置值比较函数默认将 data comparator 设置为null
.值比较函数与 data comparator 类似,只不过两个参数 a 和 b 是经过 value accessor 计算之后的值,而不是原始的数据元素。如果 a 应该在 b 前则返回小于
0
的值,如果 a 应该在 b 后面则返回大于0
的值。返回0
表示 a 和 b 的相对位置不改变。例如根据值进行排序:pie.sortValues(function(a, b) { return a - b; });
排序操作不会影响 generated arc array(生成的数组次序), 生成的数据次序与传入的数组次序保持一致。排序操作是通过修改每个生成的元素的起始角度值来实现排序的。
pie.startAngle([angle]) <源码>
如果指定了 angle 则将饼图的布局起始角度设置为指定的函数或数值并返回饼图生成器。如果没有指定则返回当前起始角度访问器默认为:
function startAngle() { return 0; }
起始角度是整个饼图的开始角度,也就是第一个扇区的开始角度。起始角度访问器只会调用一次,并传递当前数据为参数,其中
this
指向 pie generator。angle 的单位是任意的,但是如果要将饼图生成器与弧生成器结合使用则应该以弧度指定,12点钟
方向为0
度方向,并且顺时针为正。pie.endAngle([angle]) <源码>
如果指定了 angle 则将整个饼图的终止角度设置为指定的函数或数值并返回当前饼图生成器。如果没有指定 angle 则返回当前的终止角度访问器。默认为:
function endAngle() { return 2 * Math.PI; }
终止角度也就是整个饼图的结束角度,即最后一个扇区的终止角度。终止角度访问器会被调用一次病传递当前数据,其中
this
指向 pie generator,角度的单位是任意的,但是如果要将饼图生成器与弧生成器结合使用则应该以弧度指定,12点钟
方向为0
度方向,并且顺时针为正。终止角度可以被设置为 startAngle ± τ,这样就能保证 |endAngle - startAngle| ≤ τ.
pie.padAngle([angle]) <源码>
如果指定了 angle 则将饼图扇形之间的间隔设置为指定的函数或数值,并返回当前饼图生成器。如果没有指定 angle 则返回当前默认的间隔角度访问器,默认为:
function padAngle() { return 0; }
这里的间隔角度也就是两个相邻的扇形之间的间隔。间隔角度的总和等于指定的角度乘以输入数据数组中的元素数量,最大为 |endAngle - startAngle|;然后,剩余的间隔按比例按比例分配,这样每个弧的相对面积就会被保留下来。参考 pie padding animation 获取更详细的说明。间隔访问器只会被调用一次,并传递当前数据集,其中
this
上下文指向 Linesline
生成器可以用来生成线条图需要的 spline 或 polyline。线条也可以被用在其他的可视化类型中,比如 hierarchical edge bundling。d3.line() <源码>
使用默认的设置构造一个
line
生成器。Constructs a new line generator with the default settings.
line(data) <源码>
根据指定的 data 数组生成一个线条。根据与线条生成器的关联的 curve,输入数据 data 可能需要根据 x 值进行排序。如果线条生成器有 context,则线条会通过 path method 被渲染到指定的上下文中,否则返回一个 path data 字符串。
line.x([x]) <源码>
如果指定了 x 则将
x
访问器设置为指定的函数或数值并返回当前line
生成器。如果没有指定 x 则返回当前x
访问器,默认为:function x(d) { return d[0]; }
在线条被 generated 时,
x
访问器将会为输入数据中每一个 defined 的元素进行调用,并传入当前元素d
, 当前索引i
以及当前所有元素data
三个参数。默认的x
访问器假设输入的数据为一个数值类型的二维数组。如果你的数据是其他的格式或者你在渲染前想进一步处理,则应该指定一个自定义的访问器。比如,如果你的x
为 time scale 并且y
为 linear scale:var data = [ {date: new Date(2007, 3, 24), value: 93.24}, {date: new Date(2007, 3, 25), value: 95.35}, {date: new Date(2007, 3, 26), value: 98.84}, {date: new Date(2007, 3, 27), value: 99.92}, {date: new Date(2007, 3, 30), value: 99.80}, {date: new Date(2007, 4, 1), value: 99.47}, … ]; var line = d3.line() .x(function(d) { return x(d.date); }) .y(function(d) { return y(d.value); });
line.y([y]) <源码>
如果指定了 y 则将
y
访问器设置为指定的函数或数值并返回当前line
生成器。如果没有指定 y 则返回当前y
访问器,默认为:function y(d) { return d[1]; }
在线条被 generated 时,
x
访问器将会为输入数据中每一个 defined 的元素进行调用,并传入当前元素d
, 当前索引i
以及当前所有元素data
三个参数。默认的x
访问器假设输入的数据为一个数值类型的二维数组。参考 line.x 获取更多信息。line.defined([defined]) <源码>
如果指定了 defined 则将已定义的访问器设置为指定的函数或布尔值。如果没有指定 defined 则返回当前默认的已定义的访问器,默认为:
function defined() { return true; }
默认的访问器假设输入数据总是被定义的。当线条被 Areas
area generator(区域生成器)
用来在area
图中生成区域图。一个区域图由两条边界 lines 定义,可以是曲线或折线。通常情况下两条边界线共享一个 x-values (x0 = x1),仅仅是 y-value (y0 和 y1) 不一样。大多数情况下,y0
会被定义为一个常量 zero. 第一条线 (也就是 上侧线) 由x1
和y1
定义渲染。而第二条线 (也就是 基线) 由x0
和y0
定义渲染。有了 curveLinear curve,就可以生成一个顺时针方向的多边形。d3.area() <源码>
使用默认的设置构建一个区域生成器。
area(data) <源码>
根据指定的一组数据 data。根据这个区域生成器的相关 curve ,给定的输入数据可能需要在传递给区域生成器之前按
x
- 值排序。如果区域生成器被指定了 context 则区域图会调用 path method 被渲染到指定的上下文上,并且这个方法返回void
。否则会返回一个表示 path data 的字符串。area.x([x]) <源码>
如果指定了 x 则设置 x0 为 x 并且设置 x1 为
null
,返回当前区域生成器。如果没有指定 x 则返回当前x0
访问器。area.x0([x]) <源码>
如果指定看 x 则将
x0
访问器设置为指定的函数或数值并返回当前区域生成器。如果没有指定 x 则返回当前x0
生成器, 默认为:function x(d) { return d[0]; }
在区域被 generated,
x0
访问器会依次为输入的数据元素调用。并传递当前数据d
, 索引i
以及数据数组data
三个参数。默认的x0
访问器假设输入的数据为一个二元数值数组。如果你的数据是其他的不同的格式,或者需要在渲染前进行转换则你需要设置一个自定义的访问器。比如x
为 time scale 并且y
为 linear scale:var data = [ {date: new Date(2007, 3, 24), value: 93.24}, {date: new Date(2007, 3, 25), value: 95.35}, {date: new Date(2007, 3, 26), value: 98.84}, {date: new Date(2007, 3, 27), value: 99.92}, {date: new Date(2007, 3, 30), value: 99.80}, {date: new Date(2007, 4, 1), value: 99.47}, … ]; var area = d3.area() .x(function(d) { return x(d.date); }) .y1(function(d) { return y(d.value); }) .y0(y(0));
area.x1([x]) <源码>
如果制定了 x 则设置
x1
访问器为指定的函数或数值并返回区域生成器。如果x
没有指定则返回当前的x1
访问器,默认为null
表示先前计算的x0
值应该为x1
值重用。当一个区域图被 generated 时,
x1
访问器将会为每个定义的元素调用。并传递当前元素d
, 索引i
以及数据数组三个参数。参考 area.x0 获取更多信息。area.y([y]) <源码>
如果指定了 y 则设置 y0 为 y 并设置 y1 为
null
, 返回区域生成器。如果 y 没有被指定则返回当前的y0
访问器。area.y0([y]) <源码>
如果指定了 y 则设置 y0 访问器为指定的函数或数值并返回当前区域生成器。如果没有指定 y 则返回当前 y0 访问器默认为:
function y() { return 0; }
在区域被 generated 时,y0 访问器会为每个输入的元素调用并传递当前数据元素
d
, 当前索引i
以及数据数组data
。参考 area.x0 获取更多信息。area.y1([y]) <源码>
如果指定了 y 则将
y1
访问器设置为指定的函数或数值并返回当前区域生成器。如果没有指定y
则返回当前y1
访问器默认为:function y(d) { return d[1]; }
可以使用空的访问器以表明 y0 会被
y1
复用,y1
访问器会为每个定义的元素调用并传递当前数据元素d
, 索引i
以及当前数组data
三个参数。参考 area.x0 获取更多信息。area.defined([defined]) <源码>
如果指定了 defined 则将定义访问器设置为指定的函数或布尔值并返回区域生成器。如果没有指定 defined 则返回当前定义访问器默认为:
function defined() { return true; }
默认的访问器假设输入数据都是定义的。当区域图被生成时,已经定义的访问器会为每个数据元素调用,并传递当前数据元素
d
, 索引i
以及数组data
三个参数。如果给定的元素时定义的(i.e. 访问器返回真值),Curveslines 被定义为一系列二维点 [x, y],areas 类似的可以由顶线和基线定义,但是还有一个任务就是把这些离散的点转换为连续的线条: 例如如何在这些点之间进行插值,插值的方式有很多种。
插值曲线通常不会直接使用,而是传递给 line.curve 和 area.curve。例如:
var line = d3.line() .x(function(d) { return x(d.date); }) .y(function(d) { return y(d.value); }) .curve(d3.curveCatmullRom.alpha(0.5));
d3.curveBasis(context) <源码>
使用指定的控制点生成一个三次 basis spline(样条曲线)。第一个和最后一个点会被分成三个重复的点,这样就能保证线条经过第一个和最后一个点。并且曲线与第一个和第二个点之间的连线相切,同时与最后一个与倒数第二个点连线相切。
d3.curveBasisClosed(context) <源码>
使用指定的控制点生成一个闭合的三次 basis spline。当一个线段结束时,前三个控制点被重复,产生一个连续性的闭环。
d3.curveBasisOpen(context) <源码>
使用指定的控制点生成一个三次 basis spline。与 basis 不同,第一个和最后一个控制点不会被重复,这条曲线通常不会与这些点相交。
d3.curveBundle(context) <源码>
使用指定的控制点产生一个可以校正调整的三次 basis spline,校正系数根据曲线的 beta 系数确定,默认为
0.85
。这种曲线通常用在 hierarchical edge bundling 中来消除视觉混淆。这个算法是 Danny Holten 在 Hierarchical Edge Bundles: Visualization of Adjacency Relations in Hierarchical Data 中提出的。这种曲线生成方式不会实现 curve.areaStart 和 curve.areaEnd,它的设计是用来和 d3.line 结合的,而不是 d3.area。bundle.beta(beta) <源码>
根据指定的 beta 设置曲线的校正系数,系数范围为
[0, 1]
用来表示绑定强度。如果 beta 为0
则会在第一个和最后一个点之间生成一个直线,如果 beta 为1
,则会生成一个标准的 basis。例如:var line = d3.line().curve(d3.curveBundle.beta(0.5));
d3.curveCardinal(context) <源码>
使用指定的控制点生成一条三次 cardinal spline 曲线,默认 tension 为
0
.d3.curveCardinalClosed(context) <源码>
使用指定的控制点生成一条闭合的三次 cardinal spline 曲线。默认 tension 为
0
.d3.curveCardinalOpen(context) <源码>
使用指定的控制点生成一条三次 cardinal spline 曲线,与 curveCardinal 不同,生成的曲线不利用第一个和最后一个点。默认 tension 为
0
.cardinal.tension(tension) <源码>
使用指定的处于 [0, 1] 的 tension 系数设置曲线的张力,张力确定了切线的长度:张力为
1
等价于 curveLinear,张力为0
等价于 Catmull–Rom。例如:var line = d3.line().curve(d3.curveCardinal.tension(0.5));
d3.curveCatmullRom(context) <源码>
使用指定的控制点和默认值为
0.5
的 alpha 值生成一条Catmull–Rom
曲线。曲线的详细介绍参考 On the Parameterization of Catmull–Rom Curves。d3.curveCatmullRomClosed(context) <源码>
使用指定的控制点和默认值为
0.5
的 alpha 值生成一条闭合的Catmull–Rom
曲线。d3.curveCatmullRomOpen(context) <源码>
使用指定的控制点和默认值为
0.5
的 alpha 值生成一条Catmull–Rom
曲线。与 curveCatmullRom 不同的是所生成的曲线不经过第一个和最后一个控制点。catmullRom.alpha(alpha) <源码>
使用指定的 alpha 值(
[0, 1]
) 返回一条Catmull–Rom
生成器。如果 alpha 为0
则等价于 curveCardinal,如果 alpha 为1
则会生成chordal
曲线,如果 alpha 为0.5
则会生成 centripetal spline。例如:var line = d3.line().curve(d3.curveCatmullRom.alpha(0.5));
d3.curveLinear(context) <源码>
通过指定的点产生折线。
d3.curveLinearClosed(context) <源码>
产生闭合折线
d3.curveMonotoneX(context) <源码>
产生一条在
y
方向保持单调性的曲线,假设在x
方向是单调的。曲线具体描述:A simple method for monotonic interpolation in one dimension。d3.curveMonotoneY(context) <源码>
产生一条在
x
方向保持单调性的曲线,假设在y
方向是单调的。曲线具体描述:A simple method for monotonic interpolation in one dimension。d3.curveNatural(context) <源码>
产生一条 自然的 的 三次样条曲线,其二阶导数在端点设为零。
d3.curveStep(context) <源码>
产生一个分段常数函数 (阶梯函数),由水平和垂直的交替线组成。
y
值在每一对相邻x
值的中点处发生变化。d3.curveStepAfter(context) <源码>
产生一个分段常数函数 (阶梯函数),由水平和垂直的交替线组成。
y
值在x
值之后发生变化。d3.curveStepBefore(context) <源码>
产生一个分段常数函数 (阶梯函数),由水平和垂直的交替线组成。
y
值在x
值之前发生变化。Custom Curves
Curves
通常不会直接使用,而是传递给 Linkslink
用来生成从一个源点到目标点的光滑的三次贝塞尔曲线。曲线在起点和终点的切线要么是 vertical,要么是 horizontal,要么是 radial的。d3.linkVertical() <源码>
返回一个新的 link 生成器,生成的曲线在曲线的终点和起点处的切线是垂直方向的。例如在 tree diagram 中对 links 进行可视化时,可以定义为:
var link = d3.linkVertical() .x(function(d) { return d.x; }) .y(function(d) { return d.y; });
d3.linkHorizontal() <源码>
返回一个新的 link 生成器,生成的曲线在曲线的终点和起点处的切线是水平方向的。例如在 tree diagram 中对 links 进行可视化时,可以定义为:
var link = d3.linkHorizontal() .x(function(d) { return d.y; }) .y(function(d) { return d.x; });
"https://github.com/xswei/d3-shape/blob/master/src/link/index.js" title="Source" target="_blank" rel="noopener noreferrer"><源码>
根据指定的 arguments 生成
links
。arguments 是任意的。它们会被直接传递给link
生成器的访问函数。例如,使用的默认设置时,期望的参数为:link({ source: [100, 100], target: [300, 300] });
link.source([source]) <源码>
如果指定了 source 则将
source
访问器设置为指定的函数并返回当前link
生成器。如果没有指定 source 则返回当前的source
访问器,默认为:function source(d) { return d.source; }
link.target([target]) <源码>
如果指定了 target 则将
target
访问器设置为指定的函数并返回当前link
生成器。如果没有指定 target 则返回当前的target
访问器,默认为:function target(d) { return d.target; }
link.x([x]) <源码>
如果指定了 x 则将 x 访问器设置为指定的函数或数值,并返回当前
link
生成器。如果 x 没有指定则返回当前 x 访问器,默认为:function x(d) { return d[0]; }
link.y([y]) <源码>
如果指定了 y 则将 y 访问器设置为指定的函数或数值,并返回当前
link
生成器。如果 y 没有指定则返回当前 y 访问器,默认为:function y(d) { return d[1]; }
link.context([context]) <源码>
如果指定了 context,则设置上下文并返回当前
link
生成器。如果没有指定 context 则返回当前的上下文,默认为null
。如果上下文非空,则 生成的 link 会被渲染到指定的上下文中。否则会返回 path data字符串。参考 d3-path.d3.linkRadial() <源码>
返回一个新的径向 link 生成器。例如在 tree diagram 中对 links 进行可视化时,可以定义为:
var link = d3.linkRadial() .angle(function(d) { return d.x; }) .radius(function(d) { return d.y; });
linkRadial.angle([angle]) <源码>
等价于 Symbols
符号提供了几种用来表示分类的形状。符号的坐标总是位于
⟨0,0⟩
, 需要使用transform
将其移动到指定的位置(参考: SVG, Canvas)。d3.symbol() <源码>
使用默认的设置构造一个新的符号生成器。
symbol(arguments…) <源码>
使用指定的 arguments 生成一个符号。arguments 是任意的。它们会被直接传递给符号生成器的访问器。例如使用默认的设置,没有任何参数的情况下生成的是一个
64
平方像素的区域。如果符号生成器拥有 context 则符号会被渲染到此上下文中。否则会返回一个 path data 字符串。symbol.type([type]) <源码>
如果指定了 type 则将符号的类型设置为指定的函数或符号类型并返回符号生成器。如果没有指定 type 则返回当前的类型访问器,默认为:
function type() { return circle; }
参考 symbols 获取内置的符号类型。如果需要实现自己的符号类型,可以传递对象symbolType.draw。
symbol.size([size]) <源码>
如果指定了 size 则将符号的尺寸设置为指定的函数或数值并返回符号生成器。如果没有指定 size 则返回当前的尺寸访问器,默认为:
function size() { return 64; }
当使用大小对散点图进行编码时传递一个函数是非常有用的。如果你希望符号的大小适应给定的包裹矩形,而不是指定面积则可以使用 SVG’s getBBox.
symbol.context([context]) <源码>
如果指定了 context 则将上下文设置为指定的上下文并返回符号生成器。如果没有指定 context 则返回当前的上下文,默认为
null
。如果上下文非空则 在生成符号会被渲染到指定的上下文中。否则会返回一个表示符号的 path data 字符串。d3.symbols
一组包含内置符号的数组:Custom Symbol Types
符号类型不能直接使用,而是需要传递给 Stacks
有些形状类型可以堆叠,将一个形状与另一个邻近放置。例如,月销售条形图可以按照产品类别分为多个系列的条形图并垂直堆放。相当于将条形图按照类别(比如产品类型)细分并使用颜色进行编码。
堆叠图可以同时显示整体值和每个类别的值; 但是对不同类别之间进行对比是比较困难的,因为只有底部是对齐的。所以需要选择合适的 stack order(堆叠次序) 并可以考虑使用 streamgraph。(参考 grouped charts.)
与 pie generator 类似,堆叠布局生成器不会直接产生形状。它是用来计算堆叠数据的,然后传给 area generator 或者直接使用(定位条形图)。
d3.stack() <源码>
使用默认的设置构造一个新的堆叠布局生成器。
stack(data[, arguments…]) <源码>
根据指定的数据数组 data 生成一个堆叠布局,返回形式为序列数组。可以传递任意 arguments,它们会被直接传递给访问器。
Generates a stack for the given array of data, returning an array representing each series. Any additional arguments are arbitrary; they are simply propagated to accessors along with the
this
object.返回的序列由 keys accessor 决定。每个序列 i 对应第 i 个
key
。每个序列都是一组点数组,每个点 j 表示输入数据中的第 j 个元素。最后每个点都会被表示为一个数组[*y0*, *y1*]
, 其中 y0 表示这个点的下限值(基线),y1 表示这个点的上限值(顶线); y0 和 y1 之间的差值对应当前点的计算 value。每个系列的key
与 series.key 对应, 并且 index 等于 series.index. 每个点的输入数据元素对应 point.data.例如,考虑如下的表示几种水果的月销售数据的表格:
Month Apples Bananas Cherries Dates 1/2015 3840 1920 960 400 2/2015 1600 1440 960 400 3/2015 640 960 640 400 4/2015 320 480 640 400 在
JavaScript
中可以表示为对象:var data = [ {month: new Date(2015, 0, 1), apples: 3840, bananas: 1920, cherries: 960, dates: 400}, {month: new Date(2015, 1, 1), apples: 1600, bananas: 1440, cherries: 960, dates: 400}, {month: new Date(2015, 2, 1), apples: 640, bananas: 960, cherries: 640, dates: 400}, {month: new Date(2015, 3, 1), apples: 320, bananas: 480, cherries: 640, dates: 400} ];
使用这个数据创建一个堆叠布局:
var stack = d3.stack() .keys(["apples", "bananas", "cherries", "dates"]) .order(d3.stackOrderNone) .offset(d3.stackOffsetNone); var series = stack(data);
返回的结果是一个包含每个 series 的数组。每个系列在每个月都对应一个数据点,每个点都有下限值和上限值用来表示基线和顶线:
[ [[ 0, 3840], [ 0, 1600], [ 0, 640], [ 0, 320]], // apples [[3840, 5760], [1600, 3040], [ 640, 1600], [ 320, 800]], // bananas [[5760, 6720], [3040, 4000], [1600, 2240], [ 800, 1440]], // cherries [[6720, 7120], [4000, 4400], [2240, 2640], [1440, 1840]], // dates ]
每个序列通常会被传递给 area generator 来渲染出区域图,或者直接用来绘制条形图。
stack.keys([keys]) <源码>
如果指定了 keys 则将
keys
访问器设置为指定的函数或数组,并返回当前堆叠布局生成器。如果没有指定 keys 则返回当前的keys
访问器,默认为空数组。一个序列(一层) 对应一个key
。keys
通常是字符串,但是也可以是任意值。系列的key
会被直接传递给 value accessor 以计算每个数据点的值。stack.value([value]) <源码>
如果指定了 value 则将值访问器设置为指定的函数或数值并返回当前堆叠布局生成器。如果没有指定则返回当前的值访问器,默认为:
function value(d, key) { return d[key]; }
因此,默认情况下堆叠布局生成器假设输入数据是一个对象数组,每个对象都包含了一个值为数值类型的属性。参考 stack。
stack.order([order]) <源码>
如果指定了 order 则将顺序访问器设置为指定的函数或数组并返回当前堆叠布局生成器。如果没有指定 order 则返回当前顺序访问器默认为 stackOrderNone;也就是使用 key accessor 指定的次序。参考 stack orders 获取内置顺序。
如果 order 为函数则会传递生成的系列数组,并且必须返回数组。例如默认的顺序访问器被定义为:
function orderNone(series) { var n = series.length, o = new Array(n); while (--n >= 0) o[n] = n; return o; }
堆叠次序是在计算 offset 之前进行的,因此在计算次序时每个点的下限都为
0
。每个序列的索引属性在计算完次序之后才会被设置。stack.offset([offset]) <源码>
如果指定了 offset 则将偏移访问器设置为指定的函数或数组并返回当前堆叠布局。如果 offset 没有指定则返回当前的偏移访问器,默认为 stackOffsetNone; 默认会生成以
0
为基线的堆叠图,参考 stack offsets 了解内置的偏移。如果 offset 为函数,则会传递系列数组以及顺序索引。偏移函数负责计算更新每个数据点的上下限值。例如默认的偏移被定义为:
function offsetNone(series, order) { if (!((n = series.length) > 1)) return; for (var i = 1, s0, s1 = series[order[0]], n, m = s1.length; i < n; ++i) { s0 = s1, s1 = series[order[i]]; for (var j = 0; j < m; ++j) { s1[j][1] += s1[j][0] = s0[j][1]; } } }
Stack Orders
堆叠次序通常不会直接使用,而是传递给 Stack Offsets
堆叠偏移通常不会直接使用,而是传递给 stack.offset 来使用。
d3.stackOffsetExpand(series, order) <源码>
应用零基线,对每个点的值进行规范化,使顶线始终为
1
。d3.stackOffsetDiverging(series, order) <源码>
正值堆叠在零以上,而负值 stacked below zero(零下堆叠)。
d3.stackOffsetNone(series, order) <源码>
以
0
为基线。d3.stackOffsetSilhouette(series, order) <源码>
将基线向下移动,保持流图的中心始终为零。
d3.stackOffsetWiggle(series, order) <源码>
调整基线,以最小化堆叠图的摆动。推荐使用这个偏移方式创建流图并结合顺序排列方式: inside-out order 使用。参考 Stacked Graphs—Geometry & Aesthetics 获取更多信息。