我試圖避免重復 d3 中輸入和更新選擇的代碼。我已經成功地用來merge正確選擇與新資料一起出現的所有專案(在我用來append添加新資料之后)。現在我想設定一些屬性,例如r,cy和cx. 我可以在合并的選擇中執行此操作,但如果我將它們放在transition剛剛從 0,0 開始出現影片的專案后面,我希望它們只出現在正確的位置。
我希望通過某種方式將所有屬性設定行寫入一個函式,一次傳入 enter() 選擇,下一次傳入過渡合并,這樣我只需要撰寫cx一次設定行. 以下是我對偽代碼的猜測
const valueCircles = this.chartGroup.selectAll('.valueCircle')
.data(values);
valueCircles.enter()
.append('circle')
.attr('stroke-width', '1px')
.attr('stroke', '#ffffff')
.attr('opacity', '1')
.attr('class', 'dots valueCircle')
.merge(valueCircles)
.transition()
.duration(100)
.attr('r', (d) => {
if (d.y < 0.5 ) {
return 5;
} else {
return 15;
}
})
.attr('cx', (d) => {
return timescale(new Date(d.x));
})
.attr('cy', (d) => {
return valueScale(d.y)
})
這就是我認為我想要實作的目標
function setTheDynamicValues(aSelection) {
aSelection
.attr('cx', (d) => {
return timescale(new Date(d.x));
})
.attr('cy', (d) => {
return valueScale(d.y)
})
}
function updateGraph(newData) {
const valueCircles = this.chartGroup.selectAll('.valueCircle')
.data(newData);
setTheDynamicValues(valueCircles.enter());
setTheDynamicValues(valueCircles.transition().duration(100));
}
另一種描述這一點的方法是將進入元素的過渡持續時間設為 0,對現有元素設為 100,以便新元素看起來正確且現有元素具有可見的過渡。
uj5u.com熱心網友回復:
首先,D3 的選擇是不可變merge的:你的選擇沒有做任何事情。這將是正確的模式:
//here, pay attention to "let" instead of const
let valueCircles = this.chartGroup.selectAll('.valueCircle')
.data(values);
//our enter selection is called "valuesCirclesEnter"
const valueCirclesEnter = valueCircles.enter()
.append('circle')
etc...
//now, you merge the selections
valueCircles = valueCirclesEnter.merge(valueCircles);
從那時起,valueCircles包含您的更新和輸入元素。
現在,回到你的問題:
一個慣用的 D3 確實有很多重復,這就是很多人抱怨 D3 的一點。但是我們可以使用類似的方法來避免一些重復selection.call。此外,由于您想要更新選擇的轉換但沒有輸入選擇的轉換,您可以簡單地洗掉merge.
這是一個基本示例,使用一些代碼:
顯示代碼片段
const data1 = [{
x: 100,
y: 100
}, {
x: 230,
y: 20
}];
const data2 = [{
x: 10,
y: 10
}, {
x: 50,
y: 120
}, {
x: 190,
y: 100
}, {
x: 140,
y: 30
}, {
x: 270,
y: 140
}];
const svg = d3.select("svg");
draw(data1);
setTimeout(() => draw(data2), 1000);
function draw(values) {
const valueCircles = svg.selectAll('.valueCircle')
.data(values);
valueCircles.enter()
.append('circle')
.attr("class", "valueCircle")
.attr("r", 10)
.call(positionCircles);
valueCircles.transition()
.duration(1000)
.call(positionCircles)
};
function positionCircles(selection) {
selection.attr("cx", d => d.x)
.attr("cy", d => d.y)
}
<script src="https://d3js.org/d3.v7.min.js"></script>
<svg></svg>
在上面的代碼片段中,我使用一個名為positionCircles;的函式來定位輸入和更新選擇。但是,對于輸入選擇,我傳遞了一個簡單的選擇,而對于更新選擇,我傳遞了一個過渡選擇。但是功能是一樣的:
function positionCircles(selection) {
selection.attr("cx", d => d.x)
.attr("cy", d => d.y)
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/422083.html
標籤:
