领先的免费Web技术教程,涵盖HTML到ASP.NET

网站首页 > 知识剖析 正文

手把手教你D3.js 实现数据可视化极速上手到Vue应用

nixiaole 2025-01-26 23:46:18 知识剖析 10 ℃



前言

D3近年来一直是JavaScript最重要的数据可视化库之一,在创建者Mike Bostock的维护下,前景依然无量,至少现在没有能打的:

  • D3与众多其他库的区别在于无限定制的能力(直接操作SVG)。
  • 它的底层API提供对原生SVG元素的直接控制,但它也带来了高学习曲线的成本。
  • 我们将把D3和Vue结合在一起 - 使用Vue的动态数据绑定,清晰的语法和模块化结构,可以充分发挥D3的最佳性能。 根据广泛定义,D3可拆分为以下几种分库:



  1. 绝大部分的D3课程或书籍,都会着重讲解在其DOM操作功能上,但这明显与近几年来的web框架理念相违背。
  2. 用于数据可视化的D3,其核心在于使用绘图指令装饰数据,从源数据创建新的可绘制数据,生成SVG路径以及从数据和方法在DOM中创建数据可视化元素(如轴)的功能。
  3. 有许多用于管理DOM的工具,所有这些工具都可以在D3中集成数据可视化功能。这也是D3能与Vue无缝结合的原因之一。

于此,我们不需要从D3 DOM操作功能开始学起,直接通过实例来入门D3。

1. D3.js 渐进入门

以下实例的模版均为以下形式:


    
        
        Learn D3.js
    
    
        
        

First heading

复制代码

1. 选择和操作



你需要学习的第一件事是如何使用D3.js选择和操作DOM元素。该库在操作DOM方面实际上非常强大,因此理论上可以将其用作jQuery的替代品。以下代码请逐行添加运行。

// index.js
d3.select();
d3.selectAll();

d3.select('h1').style('color', 'red')
.attr('class', 'heading')
.text('Updated h1 tag');

d3.select('body').append('p').text('First Paragraph');
d3.select('body').append('p').text('Second Paragraph');
d3.select('body').append('p').text('Third Paragraph');

d3.selectAll('p').style('')
复制代码

2.数据加载和绑定


当你要创建可视化时,了解如何加载数据以及将其绑定到DOM非常重要。所以在这个实例中,你将学到这两点。


let dataset = [1, 2, 3, 4, 5];

d3.select('body')
    .selectAll('p')
    .data(dataset)
    .enter()
    .append('p') // appends paragraph for each data element
    .text('D3 is awesome!!');
    //.text(function(d) { return d; });
复制代码

3.创建一个简单的柱状图



首先需要添加一个svg标签

Bar Chart using D3.js

复制代码

然后在index.js中添加(已添加关键注释):

// 数据集
let dataset = [80, 100, 56, 120, 180, 30, 40, 120, 160];
// 定义svg图形宽高,以及柱状图间距
let svgWidth = 500, svgHeight = 300, barPadding = 5;
// 通过图形计算每个柱状宽度
let barWidth = (svgWidth / dataset.length);

// 绘制图形
let svg = d3.select('svg')
    .attr("width", svgWidth)
    .attr("height", svgHeight);

// rect,长方形
// 文档:http://www.w3school.com.cn/svg/svg_rect.asp

let barChart = svg.selectAll("rect")
    .data(dataset) //绑定数组
    .enter() // 指定选择集的enter部分
    .append("rect") // 添加足够数量的矩形
    .attr("y", d => svgHeight - d ) // d为数据集每一项的值, 取y坐标
    .attr("height", d => d) // 设定高度
    .attr("width", barWidth - barPadding) // 设定宽度
    .attr("transform", (d, i) =>  {
        let translate = [barWidth * i, 0]; 
        return "translate("+ translate +")";
    }); // 实际是计算每一项值的x坐标
复制代码

4. 在图形上方显示数值


这时就需要在上述代码中创建svg的 text文本


let text = svg.selectAll("text")
    .data(dataset)
    .enter()
    .append("text")
    .text(d => d)
    .attr("y", (d, i) => svgHeight - d - 2)
    .attr("x", (d, i) =>  barWidth * i)
    .attr("fill", "#A64C38");
复制代码

过程比较简单,就是返回文本,计算x/y坐标,并填充颜色。

5. scales: 比例尺函数

D3中有个重要的概念就是比例尺。比例尺就是把一组输入域映射到输出域的函数。映射就是两个数据集之间元素相互对应的关系。比如输入是1,输出是100,输入是5,输出是10000,那么这其中的映射关系就是你所定义的比例尺。

D3中有各种比例尺函数,有连续性的,有非连续性的,在本例子中,你将学到d3.scaleLinear() ,线性比例尺

5.1 d3.scaleLinear(),线性比例尺

使用d3.scaleLinear()创造一个线性比例尺,其中:

  • domain()是输入域
  • range()是输出域
  • 相当于将domain中的数据集映射到range的数据集中。
let scale = d3.scaleLinear().domain([1,5]).range([0,100])
复制代码

映射关系:



值得注意的是,上述代码只是定义了一个映射规则,映射的输入值并不局限于domain()中的输入域。

scale(1) // 输出:0
scale(4) // 输出:75
scale(5) // 输出:100
scale(-1) // 输出:-50
scale(10) // 输出:225
复制代码

于是我们来改造3~4的例子:

let dataset = [1,2,3,4,5];

let svgWidth = 500, svgHeight = 300, barPadding = 5;
let barWidth = (svgWidth / dataset.length);


let svg = d3.select('svg')
    .attr("width", svgWidth)
    .attr("height", svgHeight);
    
let yScale = d3.scaleLinear()
    .domain([0, d3.max(dataset)])
    .range([0, svgHeight]);
        
let barChart = svg.selectAll("rect")
    .data(dataset)
    .enter()
    .append("rect")
    .attr("y", d => svgHeight - yScale(d))
    .attr("height", d => yScale(d))
    .attr("width", barWidth - barPadding)
    .attr("transform", (d, i) => {
        let translate = [barWidth * i, 0]; 
        return "translate("+ translate +")";
    });
复制代码

然后就会得到以下图形:



6. Axes:轴



轴是任何图表的组成部分,本例子中将会用到上面讲到的比例尺函数。

let data= [80, 100, 56, 120, 180, 30, 40, 120, 160];

let svgWidth = 500, svgHeight = 300;

let svg = d3.select('svg')
    .attr("width", svgWidth)
    .attr("height", svgHeight);

// 首先是拿最大值构建x轴坐标
let xScale = d3.scaleLinear()
    .domain([0, d3.max(data)])
    .range([0, svgWidth]);
         
// 接下来是反转值,用作y轴坐标。
let yScale = d3.scaleLinear()
    .domain([0, d3.max(data)])
    .range([svgHeight, 0]);

// 横轴的API使用
let x_axis = d3.axisBottom()
    .scale(xScale);
    
// 纵轴的API使用
let y_axis = d3.axisLeft()
    .scale(yScale);
    
// 在svg中提供了如g元素这样的将多个元素组织在一起的元素。
// 由g元素编组在一起的可以设置相同的颜色,可以进行坐标变换等,类似于Vue中的