D3.js入门指南:核心API、数据绑定与图表绘制实战

作者:键盘侠时间:2026-10-22 07:03:26浏览:649

本文详解D3.js核心概念,对比其与jQuery的差异,深入解析select、data、enter、exit等关键API。通过线性与时间比例尺配置,演示如何创建SVG坐标轴,并完整展示绑定数据、绘制带圆角矩形的柱状图全过程,涵盖从DOM操作到视觉呈现的实战技巧。

D3.js基础与jQuery对比

D3是一个专注于数据可视化的JavaScript库,它支持SVG、Canvas以及HTML等多种渲染方式,结合了强大的可视化技术与数据驱动的DOM操作能力。

D3与jQuery的主要区别在于设计理念:D3采用数据驱动文档(Data-Driven Documents)的方式,而jQuery侧重于直接操作元素。在使用D3时,需要通过其特有的data()、enter()和exit()方法传入数据及回调函数,由D3自动处理元素的增删改。D3常用于构建复杂的数据可视化图表,而jQuery更多用于Web应用交互。尽管两者都提供CSS选择器和流畅的API,但D3拥有众多数据可视化扩展插件,jQuery则拥有广泛的Web应用插件库。

D3与jQuery的核心差异在于数据驱动机制与适用场景。

核心API详解

D3中最常用的基础操作方法包括选择、添加和属性设置。

d3.select(selector):该方法用于选取文档中第一个匹配指定selector的元素。若未找到匹配项,则返回一个空的选择集(注意:并非null或undefined)。

d3.selectAll(selector):与select()不同,此方法会选取所有匹配selector的元素,返回包含多个元素的选择集。

selection.append(type):当type为字符串时,该方法会将该字符串作为标签名称,创建新元素并将其追加到每个选定元素的最后一个子元素位置。

selection.attr(name, [value]):若提供了value参数,则将选择集中名为name的属性值设置为value(value可以是常量或函数);若未提供value,则返回选择集中第一个非空元素的name属性当前值。

selection.data([data[,key]]):该方法将指定数据与当前选择集中的元素进行绑定,并返回一个新的选择集。

selection.enter():返回enter选择集。当DOM元素数量少于对应数据量时,使用此方法可以添加缺失的DOM元素。例如:


var div = d3.select("body")
  .selectAll("div")
  .data([4, 8, 15, 16, 23, 42])
  .enter().append("div")
  .text(function(d) { return d; });

若body元素初始为空,上述代码会根据数据数组创建新的div元素,将其添加到body中,并将文本内容设置为对应的数值。页面最终渲染结果如下:


 <div>4</div>
 <div>8</div>
 <div>15</div>
 <div>16</div>
 <div>23</div>
 <div>42</div>

selection.exit():返回exit选择集。当DOM元素数量多于对应数据量时,使用此方法可以移除多余的DOM元素。例如,在更新数据时:

div = div.data([1, 2, 4, 8, 16, 32], function(d) { return d; });

由于此处指定了key方法用于确定数据与元素的匹配顺序,且数据[4, 8, 16]与已存在的元素匹配,因此update选择集仅包含3个div元素。此时,我们可以利用enter选择集添加3个新元素:

div.enter().append("div").text(function(d) { return d; });

同时,还需要移除不再需要的元素[15, 23, 42]:

div.exit().remove();

页面最终显示结果:


 <div>1</div>
 <div>2</div>
 <div>4</div>
 <div>8</div>
 <div>16</div>
 <div>32</div>

SVG结构与柱状图绘制

制作柱状图的基本流程涉及理解SVG结构,明确所需图形、标签及其属性。

D3.js基础与jQuery对比

柱状图示例展示。

使用D3绘制图表前,需熟悉SVG结构,明确图形所需的标签及属性。例如,制作柱状图主要涉及XY坐标轴和柱形部分。XY轴使用line标签绘制直线,text标签显示刻度文字;柱形使用rect标签绘制长方形。若需圆角长方形,可设置rect标签的rx或ry属性;若需定义位置,则需设置x和y属性等。通过逐步组合这些元素,最终形成完整的图表。

以下内容基于D3 3.x版本的API,部分接口与D3 4.0存在差异。参考文档:D3 3.x API Reference、D3 4.0 API Reference。

SVG根元素创建

创建SVG根元素。

D3绘图的第一步是创建svg元素并定义其宽高属性:


var svg = d3.select(id).append("svg")
  .attr('class', 'svg_timeline')
  .attr("width", width + margin.left + margin.right)
  .attr("height", height + margin.top + margin.bottom);

坐标轴与比例尺配置

坐标轴的绘制首先依赖于D3的比例尺,通过axis.scale([scale])方法设置或获取比例尺。比例尺主要分为三类:

定量比例尺用于连续数据(如数字);时间比例尺用于时间数据;序数比例尺用于离散数据(如名称、类别)。

例如,若需制作带有时间刻度的X轴和数字刻度的Y轴,可分别使用时间比例尺和定量比例尺(具体为线性比例尺)。

d3.scale.linear()用于创建线性比例尺;d3.time.scale()用于创建时间比例尺,其刻度和格式配置为本地时间。

确定比例尺后,还需设置输入域(domain)和输出范围(range)。例如,一个x轴的比例尺配置如下:


var x = d3.time.scale()
  .range([0, 坐标轴的宽度])
  .domain(最小日期, 最大日期);

其中最小日期和最大日期均为Date对象。随后设置X坐标轴的比例尺并创建该坐标轴:


//生成x坐标轴
var xAxis = d3.svg.axis()    //新建一个默认的坐标轴
  .scale(x)    //设置比例尺
  .ticks(d3.time.day, 1)   //指定刻度生成的方式
  .tickFormat(function(d){  //自定义刻度文字格式
    var month = d.getMonth() + 1;
    return month+'月'+ d.getDate() +'日';
  })
  .tickPadding([15]) //坐标轴线与文字之间的距离
  .tickSize(-height)
  .orient("bottom"); //位置

ticks参数的类型取决于对应比例尺的类型,此处传入的时间间隔表示刻度之间相隔一天。tickFormat允许自定义刻度的文字显示格式。

值得注意的是,若数据中对应X轴的值为字符串(如'2017-08-12'),则绑定到页面的数据需经过处理。D3提供了日期解析和格式化接口。

format.parse(string):将字符串string解析为日期对象;d3.time.format(specifier):根据给定的specifier创建本地时间格式化器。

具体示例如下:


var parseDate = d3.time.format("%Y-%m-%d").parse; //时间解析器
var date = parseDate('2017-08-12'); //将字符串解析成日期

最后,在svg元素中添加坐标轴:


//添加X轴元素
svg.append("g")
  .attr("class", "axis x")
  .attr("transform", "translate(0," + height + ")")
  .call(xAxis);

selection.call(function[, arguments…])方法用于调用指定的函数,并将选择集及后续参数一同传递给该方法。

长方形元素绘制

在柱状图中绘制长方形的具体步骤包括:将数据与页面元素绑定,创建所需的页面元素,设置每个元素的样式和位置,以及添加事件监听等。


//添加条形的元素
var bars = svg.selectAll(".barRect")
  .data(ddata)  //绑定数据
  .enter().append("g")  //创建缺少的页面元素
  .attr('class', 'barRect')
  .attr("id", function(d, i) {
    return "barRect-" + i;
  });          

//定义矩形的位置
//x为矩形最左端的位置
//y为矩形最顶端的位置
bars.append("rect")
  .attr('class','bar-rect')
  .attr("width",16)  //长方形的宽度
  .attr("y", function(d) {
    return y(d.value);   //使用比例尺确定坐标Y值
  })
  .attr("x", function(d) {
    return x(d.date) - 8;  //使用比例尺确定坐标X值
  })
  .attr("height", function(d) {  //条形的高度
    return height - y(d.value);
  })
  .attr('rx',10) //圆角
  .attr('ry',10) //圆角
  .attr('fill','url(#linear-gradient)'); //填充渐变色

作者最新文章