我正在使用crossfilter.js和d3.js v4使用ES6样式的React来尝试使用上下文刷制来创建维度图表。基本上,我拿了this example并将其转换为ES6。
我遇到的问题是selection.exit().remove()
无效,因此在每次重绘时,会有越来越多的圆圈附加到svg g元素上。创建画笔时会触发重绘。我通过运行检查
selection.exit()
.attr('class', d => {
console.log('anything');
return 'anything';
})
.remove();
但没有输出,所以我认为我的数据选择无效。
以下是上下文:
componentDidMount() {
const el = ReactDOM.findDOMNode(this); // the mounted svg element
const svg = d3.select(el)
.attr('width', 300)
.attr('height', 500);
const g = svg.append('g')
.attr('transform', 'translate(32,32)');
let circles = g.append('g')
.selectAll('circle');
const brushGroup = g.append('g')
.attr('class', 'brush')
.call(brush);
function redraw() {
const all = group.all(); // crossfilter group returns an array
xAxisGroup.call(xAxis);
yAxisGroup.call(yAxis);
circles = circles.data(all, d => d); // keyFn for data constancy
circles.enter().append('circle')
.attr('r', radius)
.attr('cx', plotX) // radius + plotX/Y are simple curry functions
.attr('cy', plotY);
circles.exit().remove(); // not working!!
}
redraw();
}
我也知道v4中d3-selection的这种变化,但我不能确定哪些行是update
,哪些是update + enter
。
非常感谢任何帮助。谢谢!
答案 0 :(得分:1)
我怀疑问题是两件事之一。可能在下面#1。用一个可以用来测试内容的工作示例来说,有点难以分辨,但是你走了:
我认为selectAll
和data
联接应该在redraw
函数中一起发生。因为您从不重做重绘函数中的selectAll
,所以您的选择将永远不会包含任何元素。如果您检查enter
函数中的exit
和redraw
选项,则enter
选项将始终包含所有数据点,因为基础选择为空。
您的数据键函数返回一个对象。由于该对象是Crossfilter的group.all
的结果,因此它们应该通过引用进行比较,但是circles.data(all, d => d.key)
会更安全。
解决方案应该是:
componentDidMount() {
const el = ReactDOM.findDOMNode(this); // the mounted svg element
const svg = d3.select(el)
.attr('width', 300)
.attr('height', 500);
const g = svg.append('g')
.attr('transform', 'translate(32,32)');
let circlesGroup = g.append('g'); // Just hang on to the group
const brushGroup = g.append('g')
.attr('class', 'brush')
.call(brush);
function redraw() {
const all = group.all(); // crossfilter group returns an array
xAxisGroup.call(xAxis);
yAxisGroup.call(yAxis);
let circles = circlesGroup // Do the selection and data join here
.selectAll('circle')
.data(all, d => d.key); // Have the key function return a key, not an object
circles.enter().append('circle')
.attr('r', radius)
.attr('cx', plotX) // radius + plotX/Y are simple curry functions
.attr('cy', plotY);
circles.exit().remove();
}
redraw();
}