D3.js制作圖表

D3是用于數(shù)據(jù)可視化的Javascript庫赠涮。使用SVG子寓,CanvasHTML。結(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è)空的選擇(但不是nullundefined)己儒。

  • 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)簽的rxry屬性冤灾,如果要定義長(zhǎng)方形的位置,需要設(shè)置xy屬性等辕近。就這樣,一部分一部分的組合到一起成為一張圖匿垄。

以下的內(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)');  //填充漸變色
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末兼丰,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子唆缴,更是在濱河造成了極大的恐慌鳍征,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,104評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件面徽,死亡現(xiàn)場(chǎng)離奇詭異艳丛,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)趟紊,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,816評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門氮双,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人织阳,你說我怎么就攤上這事眶蕉。” “怎么了唧躲?”我有些...
    開封第一講書人閱讀 168,697評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵造挽,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我弄痹,道長(zhǎng)饭入,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,836評(píng)論 1 298
  • 正文 為了忘掉前任肛真,我火速辦了婚禮谐丢,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘蚓让。我一直安慰自己乾忱,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,851評(píng)論 6 397
  • 文/花漫 我一把揭開白布历极。 她就那樣靜靜地躺著窄瘟,像睡著了一般。 火紅的嫁衣襯著肌膚如雪趟卸。 梳的紋絲不亂的頭發(fā)上蹄葱,一...
    開封第一講書人閱讀 52,441評(píng)論 1 310
  • 那天氏义,我揣著相機(jī)與錄音,去河邊找鬼图云。 笑死惯悠,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的竣况。 我是一名探鬼主播克婶,決...
    沈念sama閱讀 40,992評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼丹泉!你這毒婦竟也來了鸠补?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,899評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤嘀掸,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后规惰,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體睬塌,經(jīng)...
    沈念sama閱讀 46,457評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,529評(píng)論 3 341
  • 正文 我和宋清朗相戀三年歇万,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了揩晴。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,664評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡贪磺,死狀恐怖硫兰,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情寒锚,我是刑警寧澤劫映,帶...
    沈念sama閱讀 36,346評(píng)論 5 350
  • 正文 年R本政府宣布,位于F島的核電站刹前,受9級(jí)特大地震影響泳赋,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜喇喉,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,025評(píng)論 3 334
  • 文/蒙蒙 一祖今、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧拣技,春花似錦千诬、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,511評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至掸绞,卻和暖如春泵三,著一層夾襖步出監(jiān)牢的瞬間耕捞,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,611評(píng)論 1 272
  • 我被黑心中介騙來泰國打工烫幕, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留俺抽,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,081評(píng)論 3 377
  • 正文 我出身青樓较曼,卻偏偏與公主長(zhǎng)得像磷斧,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子捷犹,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,675評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容

  • 這里講一下怎么樣用d3.js弛饭,輸入一個(gè)數(shù)據(jù)list,根據(jù)數(shù)據(jù)畫一個(gè)帶有坐標(biāo)軸的簡(jiǎn)單直方圖.以下是目標(biāo)效果. 直方圖...
    Kaidi_G閱讀 4,825評(píng)論 1 3
  • 問答題47 /72 常見瀏覽器兼容性問題與解決方案萍歉? 參考答案 (1)瀏覽器兼容問題一:不同瀏覽器的標(biāo)簽?zāi)J(rèn)的外補(bǔ)...
    _Yfling閱讀 13,760評(píng)論 1 92
  • 對(duì)集合的操作 關(guān)于d3.attr 一個(gè)可以處理很多情況的函數(shù)侣颂,當(dāng)只傳入一個(gè)參數(shù)時(shí),如果是string枪孩,則返回該屬性...
    陳堅(jiān)生閱讀 2,536評(píng)論 0 2
  • 本教程是一個(gè)簡(jiǎn)單的入門教程憔晒,能夠幫助初學(xué)者快速掌握D3的基礎(chǔ)知識(shí)。 本節(jié)內(nèi)容介紹了添加元素蔑舞、綁定數(shù)據(jù)拒担、使用數(shù)據(jù)、矢...
    笨笨的笨小孩閱讀 2,027評(píng)論 0 1
  • 《動(dòng)物兇猛》這篇文章總體來說是作者編造出來的攻询,但是也有真實(shí)的故事从撼。那時(shí)大概是改革開發(fā)的年代了吧,我猜钧栖,故事里面出現(xiàn)...
    笨小孩__閱讀 13,478評(píng)論 1 3