大家好,
我的環境是 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)
提供你更好的寫法,至於你問的,我放棄去找答案了,文件給的頗莫名其妙的,可能要去追他的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的寫法,用事件驅動來寫,會比較清楚,現在終於看到了。