溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶(hù)服務(wù)條款》

d3.js如何實(shí)現(xiàn)數(shù)據(jù)綁定

發(fā)布時(shí)間:2021-08-18 14:58:43 來(lái)源:億速云 閱讀:270 作者:小新 欄目:web開(kāi)發(fā)

這篇文章主要介紹了d3.js如何實(shí)現(xiàn)數(shù)據(jù)綁定,具有一定借鑒價(jià)值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。

前言

d3.js 是一款上手容易的js類(lèi)庫(kù),專(zhuān)門(mén)用于繪制svg圖形圖表,其關(guān)鍵理念為data-join 意即數(shù)據(jù)綁定.搞清這個(gè)概念非常重要,它將以簡(jiǎn)潔優(yōu)雅的形式體現(xiàn)數(shù)據(jù)驅(qū)動(dòng)編程.

以下是Thinking with Joins的拙譯 ,原作者M(jìn)ike Bostock

假設(shè)你要用D3畫(huà)一副散點(diǎn)圖,因此需要生成一些 SVG circle 元素來(lái)直觀(guān)地展現(xiàn)數(shù)據(jù). 你會(huì)驚訝地發(fā)現(xiàn)D3沒(méi)有提供原生的產(chǎn)生多個(gè)DOM元素的接口,

是的,只有一個(gè) append 方法,用于產(chǎn)生單個(gè)DOM元素:

svg.append("circle") 
 .attr("cx", d.x) 
 .attr("cy", d.y) 
 .attr("r", 2.5);

但那只是單個(gè)圓,而你想要更多: 最好data*中每個(gè)元素對(duì)應(yīng)一個(gè)圓. 在你用蠻力寫(xiě)循環(huán)把圓畫(huà)出來(lái)之前,讓我們看看D3中的一個(gè)例子:

svg.selectAll("circle") 
 .data(data) 
 .enter().append("circle") 
 .attr("cx", function(d) { return d.x; }) 
 .attr("cy", function(d) { return d.y; }) 
 .attr("r", 2.5);

*此處 data是一個(gè) JSON 數(shù)組,其每個(gè)元素 由 x 和 y屬性構(gòu)成, 例如: [{"x": 1.0, "y":1.1},{"x": 2.0, "y":2.5}, …]. 另,SVG circle元素用cx,cy表達(dá)圓心坐標(biāo),r表達(dá)半徑長(zhǎng)度.

這份代碼符合你的需求,即每個(gè)元素產(chǎn)生一個(gè)圓 , 通過(guò)x和y屬性表達(dá)圓心的坐標(biāo).

selectAll("circle")是什么意思,為什么要在產(chǎn)生所有圓之前去選中根本不存在的元素呢?

原來(lái)事情是這樣的:告訴D3你的目標(biāo),而不要告訴它具體怎么做. 在這個(gè)例子中,D3知道我們的意圖是,要讓選中的"circle"元素來(lái)響應(yīng)數(shù)據(jù)的變化, selectAll即描述了這個(gè)目標(biāo);而無(wú)需一步步指揮D3產(chǎn)生多個(gè)圓.這個(gè)概念即data-join.

data-join的背后執(zhí)行了以下步驟:

  • selectAll("circle") 返回了一個(gè)空的選擇

  • 空的選擇通過(guò) data()方法將數(shù)據(jù)和DOM元素綁定,并產(chǎn)生三個(gè)虛擬的子集: enter, update and exit. enter()方法包含了待添加的數(shù)據(jù)及相應(yīng)的DOM元素的占位符;update()包含了已與數(shù)據(jù)綁定的現(xiàn)有元素.剩下待移除的部分被包含在 exit ()方法中

  • 一開(kāi)始選擇的結(jié)果是空的,因此所有數(shù)據(jù)都是待添加,將全部出現(xiàn)在enter的結(jié)果中.

  • 無(wú)需循環(huán),通過(guò).enter().append("circle")將待添加的元素一次性加入到SVG容器.

為什么要這么麻煩呢? 為什么不直接提供原生接口? data-join的優(yōu)雅之處在于抽象和解耦.上述代碼在enter()里只是專(zhuān)心處理新增的元素,而update and exit分別專(zhuān)注于處理更新和待刪除部分.這意味著你不用把所有DOM元素刪了重繪,因此得以輕松應(yīng)對(duì)實(shí)時(shí)變化的數(shù)據(jù),甚至支持一些交互(如拖動(dòng))與漸變的效果!

這里是一個(gè)處理三種狀態(tài)(增改刪)的例子:

var circle = svg.selectAll("circle") 
 .data(data); 
 
circle.enter().append("circle") 
 .attr("r", 2.5); 
 
circle 
 .attr("cx", function(d) { return d.x; }) 
 .attr("cy", function(d) { return d.y; }); 
 
circle.exit().remove();

如果我們重復(fù)運(yùn)行代碼,它會(huì)每次重新計(jì)算 data-join. 如果新的數(shù)據(jù)集比原來(lái)的少,多余元素會(huì)出現(xiàn)在 exit 中并被remove()刪除.反之亦然,新增的數(shù)據(jù)出現(xiàn)在enter()中通過(guò)append()添加DOM元素.若新老數(shù)據(jù)集大小不變,則所有數(shù)據(jù)只是更新坐標(biāo).(譯注:上文中介于enter和exit之間的代碼,update()會(huì)被隱式調(diào)用)

以joins的方式思考同時(shí)讓你的代碼更直觀(guān): 處理這三種狀態(tài)的代碼無(wú)需條件(if)和循環(huán)(for)分支,只需簡(jiǎn)單描述讓圖形去響應(yīng)數(shù)據(jù)的變化即可.如果給定的enter, update 或 exit 的選擇結(jié)果為空,則會(huì)自動(dòng)跳過(guò)相應(yīng)的代碼塊,以降低性能開(kāi)銷(xiāo).

Joins 支持在特定狀態(tài)(增/刪/改)下執(zhí)行操作.例如,可以在enter而非update代碼塊中,指定靜態(tài)的attributes(例如圓的半徑,用 "r" attribute指定) . 仰賴(lài)于精確改動(dòng)目標(biāo)元素和最小化DOM變更,你已經(jīng)極大地提升了瀏覽器渲染的表現(xiàn)! 類(lèi)似地,你可以在特定狀態(tài)下表現(xiàn)漸變等動(dòng)畫(huà)效果. 例如新增的圓可以從無(wú)到有漸變(半徑從0到2.5):

circle.enter().append("circle") 
 .attr("r", 0) 
 .transition() 
 .attr("r", 2.5);

待刪除的圓也可以逐漸收縮直至消失:

circle.exit().transition() 
 .attr("r", 0) 
 .remove();

感謝你能夠認(rèn)真閱讀完這篇文章,希望小編分享的“d3.js如何實(shí)現(xiàn)數(shù)據(jù)綁定”這篇文章對(duì)大家有幫助,同時(shí)也希望大家多多支持億速云,關(guān)注億速云行業(yè)資訊頻道,更多相關(guān)知識(shí)等著你來(lái)學(xué)習(xí)!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI