我正在使用D3创建反应性可视化。每当数据更改时,我都会大量使用这种模式:
function redraw(myData) {
// if data points decreased, remove some rectangles
d3.selectAll('rect')
.data(myData)
.exit()
.remove();
// if data points increased, add some rectangles
d3.selectAll('rect')
.data(myData)
.enter()
.append('rect');
// assign attribute values to all rectangles
d3.selectAll('rect')
.data(myData)
.attr('width', (d) => d.width)
.attr('height', (d) => d.height)
.attr('fill', 'blue');
}
有没有办法将此操作缩短为一个较长的操作链?
我看过许多{3}这样的D3例子,这些例子适合一次抽奖。我无法让他们为重画工作。
答案 0 :(得分:3)
您问...
是否可以将此操作缩短为单个长链操作? (强调我的)
是的,有:如果您使用的是D3 v5.8或更高版本,则可以利用新方法selection.join()
与update
,enter
制作一条链和exit
选择。顺便说一下,您链接的示例(由D3创建者Bostock制作)已经在使用join()
,所以它不是“一次性抽奖” 。
您的整个功能将是:
function redraw(myData) {
d3.select(foo).selectAll('rect')
.data(myData)
.join('rect')
.attr('width', (d) => d.width)
.attr('height', (d) => d.height)
.attr('fill', 'blue');
};
这是一个基本演示:
const svg = d3.select("svg");
d3.interval(function() {
redraw(getData());
}, 1500);
redraw(getData());
function redraw(myData) {
svg.selectAll('rect')
.data(myData)
.join('rect')
.attr('width', (d) => d.width)
.attr('height', (d) => d.height)
.attr('x', (d) => d.x)
.attr('y', (d) => d.y)
.style('fill', 'lavender')
.style('stroke', '#444');
};
function getData() {
return d3.range(~~(Math.random() * 20)).map(function(d) {
return {
x: Math.random() * 250,
y: Math.random() * 100,
width: 10 + Math.random() * 40,
height: 10 + Math.random() * 40,
}
});
}
<script src="https://d3js.org/d3.v5.min.js"></script>
<svg></svg>
PS :您当前的功能存在一些问题。首先,d3.selectAll
与selection.selectAll
不同(请注意我的函数中的d3.select(foo)
)。其次,在该函数中没有正确的update
,enter
和exit
选择。看看here的惯用模式。