iT邦幫忙

0

【已解決】D3js的enter、merge、exit的問題

  • 分享至 

  • xImage

大家好,
我的環境是 D3.js v7.3.0,
因為我看到有人提供這種寫法,覺得還不錯

const dataSet = [1,2,3,4,5,6]
const svg = d3.select('#myChart')
    .append('svg')
    .attr('width', width)
    .attr('height', height)
const update = svg.selectAll('rect').data(dataSet)
const enter = update.enter()
const exit = update.exit()
enter.append('rect')
    .attr()

不過就有個疑惑,關於enter、exit的順序問題。
不是應該這樣放置嗎?(後來測試真的沒差)

const enter = update.enter()
enter.append('rect')
    .attr()
const exit = update.exit()

在測試階段時,發現兩個問題想請教

const dataSet = [1,2,3,4,5,6]
const svg = d3.select('#myChart')
                .append('svg')
                .attr('width', width)
                .attr('height', height)
svg.selectAll('rect').data([1,2]).enter().append('rect') //綁定兩個data
    console.log('svg',svg);        
const existRect = svg.selectAll('rect')
    console.log('existRect',existRect);
const rect = svg.selectAll('rect').data(dataSet)//綁定六個data
    console.log('rect',rect);
const enter =  rect.enter()
    console.log('enter',enter);
//      const merge =  rect.merge()
//      console.log('merge',merge);
const exit =  rect.exit()
    console.log('exit',exit);


在上面的 demo,一開始已經綁定兩個 data 並新增兩個 rect,
接下來帶入新的dataSet時,
enter 不是應該是四個, merge 應該要 2個 ,exit 應該要 0 個嗎?
(1) 為什麼 log 出來,enter是6個,exit是2個?
(2) svg 裡明明有 merge 這個 f,如下,為什麼 rect.merge() 時會出錯? rect.enter()跟 rect.exit() 卻可以執行?


題外話,我在搜尋時比較常看到這個寫法:

const rect = svg.selectAll('rect')
    .data(dataSet)
    .enter()
    .append('rect')
    .attr('fill', 'steelblue')
    .exit()
    .remove()

我將 exit 跟 remove 往上移,沒出錯,但會跑不出圖來,如下

const rect = svg.selectAll('rect')
    .data(dataSet)
    .exit()
    .remove()
    .enter()
    .append('rect')
    .attr('fill', 'steelblue') 

所以,理論上,code 是照順序執行的,
那 .enter() 後面的,應該都是執行在 svg.enter()裡面的,
那 .enter() 後面,其實就不能放 .exit() 跟 .remove()?
應該要改成這樣?

const update = svg.selectAll('rect').data(dataSet)
update.enter()
    .append('rect')
    .attr('fill', 'steelblue');
update.exit().remove();

【已解決】
後來發現 data[1,2] 變成 dataSet時,
.enter() 的回傳值是 [空白x2,Yt,Yt,Yt,Yt]
.exit() 的回傳值是 [空白x2]
或者是 dataSet 變成 data[1,2]時,
.enter() 的回傳值是 [空白x2]
.exit() 的回傳值是 [空白x2,rect,rect,rect,rect]
【問題1的答案】->空白部分,表示不做任何動作的樣子
【問題2的答案】-> merge 錯誤使用,要這樣用才對

let rect1 = d3.selectAll("rect");
var rect2 = d3.selectAll("rect");
var z = rect1.merge(rect2);

【題外話】->題外話的敘述應該是正確的,不能那樣使用
【總結】
現在都在用join()了。
只要一開始就將svg刪除,就不必使用到 exit()。

d3.select('#myChar svg').remove()
const svg = d3.select('#myChart')
    .append('svg')
    .attr('width', width)
    .attr('height', height)
const rect = svg.selectAll('rect').data(data).join('rect')
rect.attr('fill', 'steelblue').text(d => d)
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 個回答

0
froce
iT邦大師 1 級 ‧ 2022-12-29 14:59:46
最佳解答

提供你更好的寫法,至於你問的,我放棄去找答案了,文件給的頗莫名其妙的,可能要去追他的source才會清楚。

const dataSet = [1,2,3,4,5,6]
const svg = d3.select('#myChart')
    .append('svg')
    .attr('width', width)
    .attr('height', height)
svg.selectAll('rect').data([1,2]).join('rect').attr(...
# 這個是簡寫
.join('rect')

# 等於下面這個
.join(
    enter => enter.append("rect"),
    update => update,
    exit => exit.remove()
)

說真的,以前學就覺得D3應該提供onEnter、onUpdate、onExit的寫法,用事件驅動來寫,會比較清楚,現在終於看到了。

greenriver iT邦研究生 5 級 ‧ 2022-12-30 08:33:22 檢舉

謝謝分享
我也一直覺得Chart.js、D3.js..等的文件都很難找
可能是本身就很難描述清楚吧 只能實作

froce iT邦大師 1 級 ‧ 2022-12-30 08:41:33 檢舉

我丟出來的時候發現你就已經自己找到答案了。
我學D3的時候剛好是v3和v4交接的時候,現在居然到v7了。

D3.js的文件很偏實作,v3的時候我一直都是做的出來但是完全搞不懂為啥一定要照那個順序的狀態...
現在有個join好多了。

我要發表回答

立即登入回答