D3
是用于數(shù)據(jù)可視化的Javascript庫赠涮。使用SVG
子寓,Canvas
和HTML
。結(jié)合強(qiáng)大的可視化技術(shù)和數(shù)據(jù)驅(qū)動(dòng)的DOM操作方法笋除。
D3與JQuery的區(qū)別
-
D3
是數(shù)據(jù)驅(qū)動(dòng)的斜友,JQuery
不是:我們使用JQuery
直接操縱元素;但是使用D3
時(shí)我們需要通過D3
專有的data()
垃它,enter()
和exit()
方法提供數(shù)據(jù)和回調(diào)鲜屏,然后D3
操作元素。 -
D3
通常用于數(shù)據(jù)可視化国拇;JQuery
用于創(chuàng)建Web應(yīng)用洛史。D3
有很多數(shù)據(jù)可視化擴(kuò)展;JQuery
有很多Web應(yīng)用插件酱吝。 - 兩者都是Javascript DOM操作庫也殖,提供CSS選擇器和流暢的API。
What is the difference between D3 and JQuery?
最常用的方法
d3.select(selector)
:選擇第一個(gè)匹配selector
的元素。如果沒有匹配的元素忆嗜,返回一個(gè)空的選擇(但不是null
或undefined
)己儒。d3.selectAll(selector)
:與select()
不同的是,會(huì)選擇所有匹配的元素捆毫。selection.append(type)
:如果指定的type
是一個(gè)字符串闪湾,則將這個(gè)type
(標(biāo)簽名稱)作為新元素附加到每個(gè)選定元素的最后一個(gè)子元素。selection.attr(name, [value])
:value
確定時(shí)绩卤,將selection
中名為name
的屬性值設(shè)置成value
途样。value
可以為常量或者方法。如果value
沒有給出濒憋,返回selection
中第一個(gè)非空元素的name
屬性當(dāng)前值何暇。selection.data([data[,key]])
:將數(shù)據(jù)和元素綁定起來,并返回一個(gè)新的selection
跋炕。-
selection.enter()
:返回enter selection
赖晶。此時(shí)DOM元素少于對(duì)應(yīng)的數(shù)據(jù)。用于添加缺少的DOM元素辐烂。比如:var div = d3.select("body") .selectAll("div") .data([4, 8, 15, 16, 23, 42]) .enter().append("div") .text(function(d) { return d; });
如果
body
是空的遏插,上面的代碼就會(huì)根據(jù)數(shù)據(jù)創(chuàng)建新的div
元素,然后添加到body
元素中纠修,并將文本內(nèi)容設(shè)置為對(duì)應(yīng)的數(shù)字胳嘲。頁面結(jié)果如下:<div>4</div> <div>8</div> <div>15</div> <div>16</div> <div>23</div> <div>42</div>
-
selection.exit()
:返回exit selection
。此時(shí)DOM元素多于對(duì)應(yīng)的數(shù)據(jù)扣草。用于移除多余的DOM元素了牛。比如,基于上面的例子辰妙,我們要更新數(shù)據(jù):div = div.data([1, 2, 4, 8, 16, 32], function(d) { return d; });
因?yàn)榇藭r(shí)指定了key方法(用于指定數(shù)據(jù)和元素匹配的順序等)鹰祸,并且數(shù)據(jù)[4,8,16]匹配已經(jīng)存在的元素,所以
update selection
只包含3個(gè)div元素密浑。我們可以使用enter selection
添加3個(gè)新元素:div.enter().append("div").text(function(d) { return d; });
然后蛙婴,還需要移除不需要的元素[15, 23, 42]:
div.exit().remove();
頁面結(jié)果:
<div>1</div> <div>2</div> <div>4</div> <div>8</div> <div>16</div> <div>32</div>
制作柱狀圖
使用D3
的時(shí)候,要對(duì)SVG的結(jié)構(gòu)有一個(gè)了解尔破。要繪出什么圖形街图,需要用到什么標(biāo)簽,標(biāo)簽需要定義什么屬性懒构。
比如餐济,制作一個(gè)柱狀圖,主要是XY坐標(biāo)軸和柱形胆剧。XY軸用到line
標(biāo)簽繪制直線絮姆,以及text
標(biāo)簽顯示刻度的文字。柱形用到rect
標(biāo)簽繪制長(zhǎng)方形,那如果要帶圓角的長(zhǎng)方形滚朵,我們可以設(shè)置rect
標(biāo)簽的rx
或ry
屬性冤灾,如果要定義長(zhǎng)方形的位置,需要設(shè)置x
和y
屬性等辕近。就這樣,一部分一部分的組合到一起成為一張圖匿垄。
以下的內(nèi)容是基于D3 3.x 的API移宅,有些接口跟D3 4.0
是不同的。
D3 3.x API Reference
D3 4.0 API Reference
根部的svg
D3繪圖首先要?jiǎng)?chuàng)建一個(gè)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);
坐標(biāo)軸
制作坐標(biāo)軸首先需要用到D3的比例尺椿疗。用到方法 axis.scale([scale])
漏峰,設(shè)置坐標(biāo)軸的比例尺,或者返回當(dāng)前的比例尺届榄。比例尺分為:
- 定量比例尺:連續(xù)的數(shù)據(jù)浅乔,比如數(shù)字。
- 時(shí)間比例尺:數(shù)據(jù)是時(shí)間铝条。
- 序數(shù)比例尺:離散的數(shù)據(jù)靖苇,比如名稱,類別等班缰。
比如我們要制作一個(gè)有時(shí)間刻度的X軸和一個(gè)數(shù)字刻度的Y軸贤壁,就可以使用時(shí)間比例尺和定量比例尺,或者更具體的說埠忘,線性比例尺脾拆。
-
d3.scale.linear()
:創(chuàng)建一個(gè)線性比例尺。 -
d3.time.scale()
:創(chuàng)建一個(gè)時(shí)間比例尺莹妒∶刻度和刻度格式配置為本地時(shí)間。
確定比例尺之后還需要設(shè)置輸入域和輸出范圍旨怠。比如一個(gè)x軸的比例尺為:
var x = d3.time.scale()
.range([0, 坐標(biāo)軸的寬度])
.domain(最小日期, 最大日期);
最小日期和最大日期都是Date
對(duì)象渠驼。然后設(shè)置X坐標(biāo)軸的比例尺并創(chuàng)建它:
//生成x坐標(biāo)軸
var xAxis = d3.svg.axis() //新建一個(gè)默認(rèn)的坐標(biāo)軸
.scale(x) //設(shè)置比例尺
.ticks(d3.time.day, 1) //指定刻度生成的方式
.tickFormat(function(d){ //自定義刻度文字格式
var month = d.getMonth() + 1;
return month+'月'+ d.getDate() +'日';
})
.tickPadding([15]) //坐標(biāo)軸線與文字之間的距離
.tickSize(-height)
.orient("bottom"); //位置
ticks
的參數(shù)類型取決于對(duì)應(yīng)的比例尺的類型,這里傳的參數(shù)是時(shí)間間隔运吓,也就是說刻度與刻度之間是相隔一天的渴邦。
tickFormat
則讓我們可以自定義刻度的文字格式。
值得一說的是拘哨,如果數(shù)據(jù)中對(duì)應(yīng)X軸的數(shù)據(jù)是字符串谋梭,比如‘2017-08-12’。那綁定到頁面上的數(shù)據(jù)是需要被處理的倦青。D3提供解析日期的接口以及日期格式化的接口瓮床。
-
format.parse(string)
:把一個(gè)字符串string
解析為一個(gè)日期。 -
d3.time.format(specifier)
:根據(jù)給定的specifier
創(chuàng)建一個(gè)當(dāng)?shù)貢r(shí)間格式化。
比如:
var parseDate = d3.time.format("%Y-%m-%d").parse; //時(shí)間解析器
var date = parseDate('2017-08-12'); //將字符串解析成日期
最后隘庄,在svg元素中添加坐標(biāo)軸:
//添加X軸元素
svg.append("g")
.attr("class", "axis x")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
selection.call(function[, arguments…])
方法調(diào)用指定的方法一次踢步,并把selection跟隨參數(shù)一起傳遞到方法中。
柱狀圖中的長(zhǎng)方形
具體步驟:將數(shù)據(jù)跟頁面元素綁定丑掺,并創(chuàng)建所需要的頁面元素获印,具體設(shè)置每個(gè)頁面元素的樣式位置,以及事件監(jiān)聽等街州。
//添加條形的元素
var bars = svg.selectAll(".barRect")
.data(ddata) //綁定數(shù)據(jù)
.enter().append("g") //創(chuàng)建缺少的頁面元素
.attr('class', 'barRect')
.attr("id", function(d, i) {
return "barRect-" + i;
});
//定義矩形的位置
//x為矩形最左端的位置
//y為矩形最頂端的位置
bars.append("rect")
.attr('class','bar-rect')
.attr("width",16) //長(zhǎng)方形的寬度
.attr("y", function(d) {
return y(d.value); //使用比例尺確定坐標(biāo)Y值
})
.attr("x", function(d) {
return x(d.date) - 8; //使用比例尺確定坐標(biāo)X值
})
.attr("height", function(d) { //條形的高度
return height - y(d.value);
})
.attr('rx',10) //圓角
.attr('ry',10) //圓角
.attr('fill','url(#linear-gradient)'); //填充漸變色