可视化前端初探(一)--D3.js

一.D3.js 概述

1.D3 是什么
D3 的全称是(Data-Driven Documents),翻译过来就是一个被数据驱动的文档。简而言之,就是一个主要是用来做数据可视化的 JavaScript 的函数库。由于它本质上是 JavaScript ,所以用 JavaScript 也是可以实现所有功能的,但它能大大减小你的工作量,尤其是在数据可视化方面,D3 已经将生成可视化的复杂步骤精简到了几个简单的函数,你只需要输入几个简单的数据,就能够转换为各种绚丽的图形。

2.什么是数据可视化以及为什么要数据可视化

将枯燥乏味复杂的数据以图形的方式表现出来,这就是数据可视化。如现在有一组数据【5,15,23,78,110,57,29,34,71】,这里的数据不多,还是比较容易直接看出它们的大小关系,但更直观的是用图形显示,如下图:

数据可视化条形图.png

通过图形的显示,能很清楚地知道他们的大小关系。这只是D3.js这个框架的一个应用示例,它具有更强大的功能。

3.为什么用D3这类js框架来做前端数据可视化

就拿上面数据可视化条形图来举例子,我们用原生js来实现这个效果。

目标:用横向柱状图来直观显示以下数据
var data = [5,15,23,78,110,57,29,34,71];

HTML代码:

<html>
<head>
</head>
<body>
    <div id="barChart"></div>
</body>
</html>

css代码:

#barChart{
    background:#f0f0f0;
    padding:10px;
    font-family:Verdana;
        color:white;
}
#barChart .bar{
    left:0px;
    height:20px;
    background:blue;
    margin:5px;
}

js代码:

//要展示的数据对象
var data =  [5,15,23,78,110,57,29,34,71];;

window.onload = function(){
    //计算data的长度
    var len = data.length;

    //获取容器DOM对象
    var barChart = document.querySelector("#barChart");

    //创建len个div对象,并设置其属性
    for(var i=0;i<len;i++){
        //创建一个新DOM元素
        var e = document.createElement("div");
        //设置元素的CSS类为bar
        e.setAttribute("class", "bar");
        //设置元素宽度为对应数据值
        e.style.width = data[i] + 50;
        //设置元素的文本为对应数据值
        e.innerText = data[i];
        //向容器追加此DIV对象
        barChart.appendChild(e);
    }
};

可以看到哪怕只是一个很简单很基础的数据图表,也要写不少js代码,当可视化数据越来复杂时,就需要D3这样的封装库来提高开发效率了。

4.D3的几个特点概述

(1). d3.js不是一个图形绘制库,依赖于标准的web技术来绘制可视化元素,比如 HTML、SVG、CSS。
(2).d3.js是一个基于集合概念的DOM操作库,它对DOM操作进行了封装。和jQuery类似,d3依赖于选择符选 中一组元素,建立一个集合,然后使用集合对象的方法操作DOM。
(3).d3.js的大量功能集中在数据处理方面,要将数据映射到图形,有很多琐碎的工作,比如数据范围的变换、插值的计算、布局的 计算等等
(4).d3.js的核心是对数据和可视化元素的匹配,一个数据对应一个可视化元素,一个 数值对应一个可视化元素的属性。d3封装了这个匹配的复杂过程,让我们得以简单的 通过声明数据和可视化元素来完成数据可视化的任务。

4.D3的下载和使用
D3官网 里面有详尽的文档,只不过是英文的
D3github地址 里面有详细的安装和使介绍

二.D3.js 语法基础

1.选择集
使用 d3.select() 或 d3.selectAll() 选择元素后返回的对象,就是选择集。
D3 能够连续不断地调用函数,列如:d3.select().selectAll().text(),这称为链式语法,和 JQuery 的语法很像。如下示例,用 D3 来更改 文本和样式

<html> 
  <head> 
        <meta charset="utf-8"> 
        <title>HelloWorld</title> 
  </head> 
    <body> 
        <p>Hello World 1</p>
        <p>Hello World 2</p>
        <script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script> 
        <script>  
          var p = d3.select("body")
          .selectAll("p")
          .text("http://www.jianshu.com");

          //修改段落的颜色和字体大小
          p.style("color","red").style("font-size","22px");           
        </script> 
    </body> 
</html>
运行结果

2.选择元素和绑定数据
(1)选择元素

d3.select():是选择所有指定元素的第一个
d3.selectAll():是选择指定元素的全部

var body = d3.select("body"); //选择文档中的body元素
var p1 = body.select("p");      //选择body中的第一个p元素
var p = body.selectAll("p");    //选择body中的所有p元素
var p = body.selectAll(".car");    //选择body中的所有类名为car的元素
var svg = body.select("svg");   //选择body中的svg元素
var rects = svg.selectAll("rect");  //选择svg中所有的svg元素

(2)绑定数据
D3 一个很强大的特点是能将数据绑定到 DOM 上,也就是绑定到文档上。
例如网页中有段落元素 <span> 和一个整数 100,于是可以将整数 100 与 <span>绑定到一起。绑定之后,当需要依靠这个数据才操作元素的时候,会很方便。

D3 中是通过以下两个函数来绑定数据的:
datum():绑定一个数据到选择集上
data():绑定一个数组到选择集上,数组的各项值分别与选择集的各元素绑定

接下来分别使用 datum() 和 data(),将数据绑定到以下HTML元素上。

<p>我爱简书</p>
<p>I love jianshu</p>

用datum()实现

var str = "nightzing";
var body = d3.select("body");
var p = body.selectAll("p");
p.datum(str);
p.text(function(d, i){
    return "第 "+ i + " 个元素绑定的数据是 " + d;
});
运行结果

在上面的代码中,用到了一个无名函数 function(d, i)。当选择集需要使用被绑定的数据时,常需要这么使用。其包含两个参数,其中:

d 代表数据,也就是与某元素绑定的数据。
i 代表索引,代表数据的索引号,从 0 开始。

用data()实现

var dataset = ["I like food","I like gaoxiao"];

var body = d3.select("body");
var p = body.selectAll("p");

p.data(dataset)
  .text(function(d, i){
      return d;
  });
运行结果

以上代码也用到了一个无名函数 function(d, i),其对应的情况如下:

当 i == 0 时, d 为 I like food。
当 i == 1 时, d 为 I like gaoxiao。
此时,元素与数组 dataset 的三个字符串是一一对应的,因此,在函数 function(d, i) 直接 return d 即可。

(3)插入元素
插入元素涉及的函数有两个:

append():在选择集末尾插入元素
insert():在选择集前面插入元素

HTML元素同上,以下代码是插入元素的示例。

/* 在 body 的末尾添加一个 p 元素 */
body.append("p")
    .text("append p element")
/* 在 body 中 id 为 car 的元素前添加一个段落元素 */
body.insert("p","#car")
  .text("insert p element");

(4) 删除元素
删除一个元素时,对于选择的元素,使用 remove 即可,例如:

var p = body.select("#car");
p.remove();

三.D3.js 实战

基础讲完了,下面就为大家介绍几个D3实战的例子, D3 提供了许多的 SVG 图形的生成器,它们都是只支持 SVG 的。因此,在D3中使用 SVG 画布来绘制图表是很常见也是被推荐的一种方式。

1.横向条形图
在文章最开始介绍了用原生js来绘制简单的横向条形图,现在来介绍下用D3来绘制类似的效果。看D3代码之前可以先来简单的复习一下SVG基本知识,可以看看我之前的一篇文章,SVG全攻略

目标:用横向柱状图来直观显示以下数据
var data = [5,15,23,78,110,57,29,34,71];
为了代码简洁方便,直接用数值的大小来表示矩形的像素宽度,同时为了方便理解,元素和样式都都直接在D3的js代码中实现,之前用原生js实现的例子那里的html元素和css样式都可以不要了,直接写下面的代码即可实现效果

var rectHeight = 25; //每个矩形所占的像素高度(包括空白)
var data = [5,15,23,78,110,57,29,34,71];
svg.selectAll("rect")
.data(dataset)
.enter()
.append("rect")
.attr("x",20)
.attr("y",function(d,i){
return i * rectHeight;
})
.attr("width",function(d){
return d;
})
.attr("height",rectHeight-2)
.attr("fill","blue");

运行结果

这段代码最主要的部分是:

svg.selectAll("rect")   //选择svg内所有的矩形
    .data(dataset)  //绑定数组
    .enter()        //指定选择集的enter部分
    .append("rect") //添加足够数量的矩形元素

有数据,而没有足够图形元素的时候,使用此方法可以添加足够的元素。
添加了元素之后,就需要分别给各元素的属性赋值。在这里用到了 function(d, i),前面已经讲过,d 代表与当前元素绑定的数据,i 代表索引号。给属性赋值的时候,是需要用到被绑定的数据,以及索引号的。最后一行代码:
.attr("fill","blue")
是给矩形元素设置颜色。正式开发中推荐写在 CSS 文件中去,方便归类和修改。这里为了便于理解,将样式直接写到元素里。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,905评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,140评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,791评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,483评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,476评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,516评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,905评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,560评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,778评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,557评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,635评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,338评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,925评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,898评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,142评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,818评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,347评论 2 342