我将数据嵌套到3个级别中,需要动态更新它们。更重要的是,由于我需要一些悬停行为,因此中级元素需要实际显示在低级元素的TOP上,因此我在输入/更新/退出/合并模式方面遇到麻烦应该看起来像。 (不需要为高级显示任何元素。)
我现在拥有的代码成功更新了数据,但根本没有渲染矩形,而是给了我一个错误Uncaught TypeError: this.setAttribute is not a function
。
请问如何解决此问题?
这是更新前的样子:
这是更新后的样子:
Here's a CodePen with the code Below
```
let width = 0.9 * window.innerWidth,
height = 0.9 * window.innerHeight,
colors = ['darkviolet', 'steelblue', 'coral', 'Turquoise', 'firebrick', 'mediumslateblue', 'palevioletred', 'green', 'aqua'];
let data1 =
[{"group":"A","segment":"1","item":"1"},
{"group":"A","segment":"1","item":"2"},
{"group":"A","segment":"1","item":"3"},
{"group":"A","segment":"2","item":"4"},
{"group":"A","segment":"2","item":"5"},
{"group":"A","segment":"2","item":"6"},
{"group":"A","segment":"3","item":"7"},
{"group":"A","segment":"3","item":"8"},
{"group":"A","segment":"3","item":"9"},
{"group":"B","segment":"4","item":"1"},
{"group":"B","segment":"4","item":"2"},
{"group":"B","segment":"4","item":"3"},
{"group":"B","segment":"5","item":"4"},
{"group":"B","segment":"5","item":"5"},
{"group":"B","segment":"5","item":"6"},
{"group":"B","segment":"6","item":"7"},
{"group":"B","segment":"6","item":"8"},
{"group":"B","segment":"6","item":"9"},
{"group":"C","segment":"7","item":"1"},
{"group":"C","segment":"7","item":"2"},
{"group":"C","segment":"7","item":"3"},
{"group":"C","segment":"8","item":"4"},
{"group":"C","segment":"8","item":"5"},
{"group":"C","segment":"8","item":"6"},
{"group":"C","segment":"9","item":"7"},
{"group":"C","segment":"9","item":"8"},
{"group":"C","segment":"9","item":"9"}],
data2 =
[{"group":"A","segment":"1","item":"1"},
{"group":"A","segment":"8","item":"2"},
{"group":"A","segment":"9","item":"3"},
{"group":"A","segment":"2","item":"4"},
{"group":"A","segment":"2","item":"5"},
{"group":"A","segment":"2","item":"6"},
{"group":"A","segment":"5","item":"7"},
{"group":"A","segment":"3","item":"8"},
{"group":"A","segment":"3","item":"9"},
{"group":"B","segment":"4","item":"1"},
{"group":"B","segment":"4","item":"2"},
{"group":"B","segment":"7","item":"3"},
{"group":"B","segment":"5","item":"4"},
{"group":"B","segment":"5","item":"5"},
{"group":"B","segment":"5","item":"6"},
{"group":"B","segment":"5","item":"7"},
{"group":"B","segment":"6","item":"8"},
{"group":"B","segment":"6","item":"9"},
{"group":"C","segment":"7","item":"1"},
{"group":"C","segment":"7","item":"2"},
{"group":"C","segment":"3","item":"3"},
{"group":"C","segment":"8","item":"4"},
{"group":"C","segment":"8","item":"5"},
{"group":"C","segment":"8","item":"6"},
{"group":"C","segment":"9","item":"7"},
{"group":"C","segment":"6","item":"8"},
{"group":"C","segment":"1","item":"9"}];
let button = d3.select('body')
.append('button')
.attr('type', 'button')
.style('display', 'block')
.text('Update')
.on('click', function() { update(data2) });
var svg = d3.select('body').append('svg')
.attr('width', width)
.attr('height', height)
.append('g');
let color = d3.scaleOrdinal().range(colors);
update(data1);
function getxy(data) {
let grouped = Array.from(d3.group(data, d=> d.group, d=> d.segment), ([key, value]) => ({key, value}));
grouped.forEach(function(s) {
s.value = Array.from(s.value, ([key, value]) => ({key, value}));
s.value.forEach(function(d) {
d.start = d3.min(d.value, function(t) { t.segment = +t.segment; t.item = +t.item; return +t.item });
d.end = d3.max(d.value, function(t) { return t.item });
d.key = +d.key;
d.group = s.key;
})
})
let x1 = d3.scaleBand()
.domain([1, 2, 3, 4, 5, 6, 7, 8, 9])
.range([width*0.05, width])
.padding(0.0);
let y1 = d3.scaleBand()
.domain(['A', 'B', 'C'])
.range([10, height])
.padding(0.1);
return [x1, y1, grouped];
}
function update(data) {
let xy = getxy(data);
let x = xy[0], y = xy[1], groupedData = xy[2];
let barsAll = svg
.selectAll('.bars')
.data(groupedData);
barsAll.exit().remove();
let barsEnter = barsAll
.enter()
.append('g')
.attr('class', 'bars');
barsEnter = barsEnter.merge(barsAll);
let segmentsAll = barsEnter
.selectAll('.segments')
.data(function(d) { return d.value });
segmentsAll.exit().remove();
let segmentsEnter = segmentsAll.enter();
let bitsAll = segmentsEnter
.selectAll('.bits')
.data(function(d) { return d.value });
bitsAll.exit().remove();
let bitsEnter = bitsAll
.enter()
.append('circle')
.attr('class', 'bits')
.attr('r', width*0.05)
.attr('stroke', 'none');
bitsEnter = bitsEnter.merge(bitsAll);
bitsEnter
.attr('cx', function(d) { return x(d.item) })
.attr('cy', function(d) { return y(d.group) + y.bandwidth()/2 })
.attr('fill', function(d) { return color(d.segment) });
segmentsEnter.append('rect')
.attr('stroke', 'black')
.attr('class', 'segments')
.style('fill-opacity', 0.2);
segmentsEnter = segmentsEnter.merge(segmentsAll);
segmentsEnter
.attr('fill', function(d) { return color(d.key) })
.attr('height', y.bandwidth()*0.75)
.attr('x', function(d) { return x(d.start) - width*0.05 })
.attr('y', function(d) { return y(d.group) + y.bandwidth()*0.125 })
.attr('width', function(d) { return x(d.end) - x(d.start) + width*0.1 });
}
```
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://d3js.org/d3-array.v2.min.js"></script>
答案 0 :(得分:0)
好吧,通过绕过中级段和低级位(而不是顶级条)上的“合并”步骤,我终于可以破解补丁了。 Working pen
仍然开放以寻求他人的帮助,因为我觉得我应该真正掌握整个流程的全部内容-更新,输入,退出,合并-在某个时候。
let width = 0.9 * window.innerWidth,
height = 0.9 * window.innerHeight,
colors = ['darkviolet', 'steelblue', 'coral', 'Turquoise', 'firebrick', 'mediumslateblue', 'palevioletred', 'green', 'aqua'];
let data1 =
[{"group":"A","segment":"1","item":"1"},
{"group":"A","segment":"1","item":"2"},
{"group":"A","segment":"1","item":"3"},
{"group":"A","segment":"2","item":"4"},
{"group":"A","segment":"2","item":"5"},
{"group":"A","segment":"2","item":"6"},
{"group":"A","segment":"3","item":"7"},
{"group":"A","segment":"3","item":"8"},
{"group":"A","segment":"3","item":"9"},
{"group":"B","segment":"4","item":"1"},
{"group":"B","segment":"4","item":"2"},
{"group":"B","segment":"4","item":"3"},
{"group":"B","segment":"5","item":"4"},
{"group":"B","segment":"5","item":"5"},
{"group":"B","segment":"5","item":"6"},
{"group":"B","segment":"6","item":"7"},
{"group":"B","segment":"6","item":"8"},
{"group":"B","segment":"6","item":"9"},
{"group":"C","segment":"7","item":"1"},
{"group":"C","segment":"7","item":"2"},
{"group":"C","segment":"7","item":"3"},
{"group":"C","segment":"8","item":"4"},
{"group":"C","segment":"8","item":"5"},
{"group":"C","segment":"8","item":"6"},
{"group":"C","segment":"9","item":"7"},
{"group":"C","segment":"9","item":"8"},
{"group":"C","segment":"9","item":"9"}],
data2 =
[{"group":"A","segment":"1","item":"1"},
{"group":"A","segment":"8","item":"2"},
{"group":"A","segment":"9","item":"3"},
{"group":"A","segment":"2","item":"4"},
{"group":"A","segment":"2","item":"5"},
{"group":"A","segment":"2","item":"6"},
{"group":"A","segment":"5","item":"7"},
{"group":"A","segment":"3","item":"8"},
{"group":"A","segment":"3","item":"9"},
{"group":"B","segment":"4","item":"1"},
{"group":"B","segment":"4","item":"2"},
{"group":"B","segment":"7","item":"3"},
{"group":"B","segment":"5","item":"4"},
{"group":"B","segment":"5","item":"5"},
{"group":"B","segment":"5","item":"6"},
{"group":"B","segment":"5","item":"7"},
{"group":"B","segment":"6","item":"8"},
{"group":"B","segment":"6","item":"9"},
{"group":"C","segment":"7","item":"1"},
{"group":"C","segment":"7","item":"2"},
{"group":"C","segment":"3","item":"3"},
{"group":"C","segment":"8","item":"4"},
{"group":"C","segment":"8","item":"5"},
{"group":"C","segment":"8","item":"6"},
{"group":"C","segment":"9","item":"7"},
{"group":"C","segment":"6","item":"8"},
{"group":"C","segment":"1","item":"9"}];
let button = d3.select('body')
.append('button')
.attr('type', 'button')
.style('display', 'block')
.text('Update')
.on('click', function() { update(data2) });
var svg = d3.select('body').append('svg')
.attr('width', width)
.attr('height', height)
.append('g');
let color = d3.scaleOrdinal().range(colors);
function getxy(data) {
let grouped = Array.from(d3.group(data, d=> d.group, d=> d.segment), ([key, value]) => ({key, value}));
grouped.forEach(function(s) {
s.value = Array.from(s.value, ([key, value]) => ({key, value}));
s.value.forEach(function(d) {
d.start = d3.min(d.value, function(t) { t.segment = +t.segment; t.item = +t.item; return +t.item });
d.end = d3.max(d.value, function(t) { return t.item });
d.key = +d.key;
d.group = s.key;
})
})
let x1 = d3.scaleBand()
.domain([1, 2, 3, 4, 5, 6, 7, 8, 9])
.range([width*0.05, width])
.padding(0.0);
let y1 = d3.scaleBand()
.domain(['A', 'B', 'C'])
.range([10, height])
.padding(0.1);
return [x1, y1, grouped];
}
function update(data) {
let xy = getxy(data);
let x = xy[0], y = xy[1], groupedData = xy[2];
// update
let barsAll = svg
.selectAll('.bars')
.data(groupedData);
// exit
barsAll.exit().remove();
// enter
let barsEnter = barsAll
.enter();
barsEnter = barsEnter.merge(barsAll).append('g');
barsEnter.selectAll('.segments').remove();
d3.selectAll('.segments').remove();
let segmentsAll = barsEnter
.selectAll('.segments')
.data(function(d) { return d.value });
segmentsAll.exit().remove();
let segmentsEnter = segmentsAll
.enter();
let bitsAll = segmentsEnter
.selectAll('.bits')
.data(function(d) { return d.value });
bitsAll.exit().remove();
bitsAll
.enter()
.append('circle')
.attr('class', 'bits')
.attr('r', width*0.05)
.attr('stroke', 'none')
.attr('cx', function(d) { return x(d.item) })
.attr('cy', function(d) { return y(d.group) + y.bandwidth()/2 })
.attr('fill', function(d) { return color(d.segment) });
// bitsEnter = bitsEnter.merge(bitsAll);
bitsAll
.attr('cx', function(d) { return x(d.item) })
.attr('cy', function(d) { return y(d.group) + y.bandwidth()/2 })
.attr('fill', function(d) { return color(d.segment) });
segmentsEnter
.append('rect')
.attr('class', 'segments')
.attr('stroke', 'black')
.style('fill-opacity', 0.2)
.attr('fill', function(d) { return color(d.key) })
.attr('height', function() { return y.bandwidth()*0.75 })
.attr('x', function(d) { return x(d.start) - width*0.05 })
.attr('y', function(d) { return y(d.group) + y.bandwidth()*0.125 })
.attr('width', function(d) { return x(d.end) - x(d.start) + width*0.1 });
segmentsAll
.attr('fill', function(d) { return color(d.key) })
.attr('height', function() { return y.bandwidth()*0.75 })
.attr('x', function(d) { return x(d.start) - width*0.05 })
.attr('y', function(d) { return y(d.group) + y.bandwidth()*0.125 })
.attr('width', function(d) { return x(d.end) - x(d.start) + width*0.1 });
//segmentsAll = segmentsEnter.merge(segmentsAll);
// segmentsEnter
// .attr('fill', function(d) { return color(d.key) })
// .attr('height', function() { return y.bandwidth()*0.75 })
// .attr('x', function(d) { return x(d.start) - width*0.05 })
// .attr('y', function(d) { return y(d.group) + y.bandwidth()*0.125 })
// .attr('width', function(d) { return x(d.end) - x(d.start) + width*0.1 });
}
update(data1);
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.13.0/d3.js"></script>
<script src="https://d3js.org/d3-array.v2.min.js"></script>