D3实现柱形图

548 阅读5分钟

这是我参与8月更文挑战的第4天,活动详情查看:8月更文挑战

d3实现柱形图

比例尺
  • scaleBand分段比例尺

    • 分段比例尺类似于序数比例尺,区别在于分段比例尺的的定义域的值可以是连续的数值类型而离散的值域则是将连续的定义域范围划分为均匀的分段。
    • 分段通常用于包含序数或类别维度的条形图。
    • 创建分段比例尺的方法是:d3.scaleBand()
  • scaleLinear 线性比例尺

    • 线性比例尺的创建方法是d3.scaleLiner()
    • 默认定义域domain为[0, 1],默认值域range是[0, 1],默认调用插值器方法interpolator
    • 默认flase了clamp方法。它是良好支持连续定量的比例尺。
    • 每一个 range 中的值 y 都可以被表示为一个函数:y = mx + b,其中 x 为对应的 domain 中的值。
  • 连续比例尺 Continuous Scales

  • 连续比例尺是一种比例尺类型,用连续定量的定义域映射连续的值域,具体包括:线性比例尺、指数比例尺、对数比例尺、定量恒等比例尺、线性时间比例尺、线性颜色比例尺。

  • 连续比例尺有以下几种通用方法:

  • continuousScale(x):向比例尺函数中传入一个定义域内的值,返回在值域内对应的值。如果给定的 x 不在 domain 中,并且 clamping 没有启用,则返回的对应的值也会位于 range 之外,这是通过映射值推算出来的。

  • continuousScale.invert(y):向比例尺函数的invert方法中传入一个值域内的值,返回定义域内对应的值。反向映射在交互中通常很有用,根据鼠标的位置计算对应的数据范围。如果给定的 y 位于 range 外面,并且没有启用 clamping 则会推算出对应的位于 domain 之外的值。这个方法仅仅在 range 为数值时有用。如果 range 不是数值类型则返回 NaN。

  • continuousScale.domain( [numbers] ):将数值数组指定为当前比例尺的定义域或获取当前比例尺定义域的拷贝,数组包含两个或两个以上元素,如果给定的数组中的元素不是数值类型,则会被强制转为数值类型。对于连续比例尺来说,定义域数值数组通常包含两个值,但是如果指定大于两个值的话会生成一个分位数的比例尺。

  • continuousScale.range( [values] ):指定当前比例尺的值域或获取当前比例尺值域的拷贝。数组中元素不一定非要是数值类型,但如果要使用 invert 则 range 必须指定为数值类型。

  • continuousScale.rangeRound( [values] ):代替range()使用的话,比例尺的输出值会进行四舍五入的运算,结果为整数。

  • continuousScale.clamp( [boolean] ):默认false,表示当比例尺接收一个超出定义域的值时,依然能按同样的计算方法得到一个值,这个值可以是超出值域范围的。当为true时,任何超出值域范围的值都会被收缩到值域范围内。

  • continuousScale.interpolate( interpolate ):设置比例尺的值域插值器,插值器函数被用来在两个相邻的来自 range 值之间进行插值。

  • continuousScale.nice( [count] ):将定义域的范围扩展成比较理想的形式。如定义域为[0.500000543, 0.899999931]时,使用nice()后可以将定义域变成[ 0.5, 0.9 ]。应用nice()方法后,定义域会变成比较工整的形式,但不是四舍五入。

  • continuousScale.ticks( [count] ):默认返回一个近似的用来表示比例尺定义域的数组。如果传入数值参数count,比例尺会以count为参考来根据定义域计算具体的ticks。不传count时默认count为10.

  • continuousScale.tickFormat( count[, format] ):返回一个调整ticks数组元素的函数。ticks数组元素也叫刻度值。注意参数count的数值应与ticks中的参数保持一致。可选的format指定符可以让开发者自定义ticks数组元素的格式,并且定义后会自动设置格式的精度,例如将数字格式化为百分比。

  • continuousScale.copy():返回一个当前比例尺的拷贝。返回的拷贝和当前比例尺之间不会相互影响。

柱状图绘制思路和流程
  • 坐标轴的实现

    • 线性比例尺的对应关系是连续的,而序数比例尺的对应关系是离散的。
    • 分析柱状图的展现意义可以得出x轴应该选用序数比例尺,而y轴选用线性比例尺。
    • d3.scale.ordinal()创建了一个序数比例尺。
    • ordinal.domain()设置了该比例尺的定义域。
    • ordinal.rangRoundBands()设置了值域。
    • 同理,d3.scale.linear()创建了一个线性比例尺。
    • linear.domain()定义定义域,linear.range()定义值域。
    • 接着,我们用d3.svg.axis()创建了两个坐标轴,把比例尺应用到它们上面,并且用axis.orient()设置了坐标轴的刻度尺的方向。
    • 最后,添加SVG元素,用call()把定义好的坐标轴与SVG元素联系起来。
  • 柱子的实现

    • 在SVG中可以使用rect元素来画。
    • 先选择到main下所有bar类的元素(此时选择到的是一个空的集合)
    • 把dataset.y绑定到这个集合上,用enter()对比绑定的数组元素个数与集合中的SVG元素个数,与append()搭配使用,会自动补齐至两边个数相等。
    • 每一次的append都对应dataset.y中的一个数组元素。利用前面创建的比例尺函数计算出值并赋给举行元素的x、y属性。