使用 d3 根据索引优雅地执行不同的操作



我正在尝试使用 d3 为我的图形制作图例,我想我可以为每行使用带有以下 HTML 的表格:

<tr>
<td class="swatch" style="background: red;"></td>
<td>user</td>
<td>123</td>
</tr>

最终结果看起来像这样。

我以以下形式将我的数据整齐地放置在每一行上:

{color: 'red', key: 'user', value: 123}

我正在使用以下代码来创建单元格:

let cells = d3.selectAll('tr').selectAll('td')
.data(function (d) {
return [d.color, d.key, d.value];
});
cells.enter().append('td').merge(cells)
.text(function (d, i) {
return i == 0 ? '' : d;
})
.style('background', function(d, i) {
return i == 0 ? d : '';
})
.each(function(d, i) {
if (i == 0) {
this.classList.add('swatch');
}
});

代码工作正常,但重复的i == 0检查以特殊处理第一个单元格的行为,它看起来非常丑陋。我可以使用更清洁的方法吗?

似乎也许我应该使用text设置所有内容并使用 CSS 将其样式设置为色板,但这是不可能的。

由于不同的表单元格的操作方式完全不同,因此可以使用多个追加和类来分隔元素。它看起来像这样:

let cells = d3.select('tbody').selectAll('tr').data(bindData);
let cellsEnter = cells.enter().append('tr');
let swatches = cellsEnter.append('td').classed('swatch', true);
d3.selectAll('table .swatch')
.style('background', function (d) { return d.color });
let otherCells = d3.selectAll('table tr').selectAll('.other')
.data(function (d) {
return [d.key, d.value];
});
otherCells.enter()
.append('td').classed('other', true)
.merge(otherCells).text(function (d) { return d; });

这是一个工作片段:

function updateData(bindData) {
let cells = d3.select('tbody').selectAll('tr').data(bindData);
let cellsEnter = cells.enter().append('tr');
let newSwatches = cellsEnter.append('td').classed('swatch', true);
d3.selectAll('table .swatch')
.style('background', function (d) { return d.color });
let otherCells = d3.selectAll('table tr').selectAll('.other').data(function (d) {
return [d.key, d.value];
});
otherCells.enter()
.append('td').classed('other', true)
.merge(otherCells).text(function (d) { return d; });
}
var data = [
{ color: 'red', key: 'agnes', value: '1' },
{ color: 'green', key: 'bernard', value: '2' },
{ color: 'blue', key: 'connie', value: '3' }
];
updateData(data);
.swatch {
display: inline-block;
height: 10px;
width: 10px;
}
<script src="https://d3js.org/d3.v4.js"></script>
<div id="legend">
<table>
<tbody>
</tbody>
</table>
</div>

你真的需要为此建立一个html表吗?将数据映射到<ul>列表中可能更自然,项目符号颜色由传入数据设置:

var data = [
{ color: "red", user: "Bob", value: 123 },
{ color: "orange", user: "Carol", value: 234 },
{ color: "green", user: "Ted", value: 345 },
{ color: "blue", user: "Alice", value: 1234 }
];
var list = d3.select("#userList")
.selectAll("li")
.data(data);
var item = list.enter()
.append("li")
.attr("class", "swatch")
.style("color", d => d.color);
var keys = item
.append("span")
.text(d => d.user);
var vals = item
.append("pre")
.text(d => d.value);
.swatch {
list-style-type: square;
}
.swatch span {
display: inline-block;
width: 50px;
}
.swatch pre {
display: inline-block;
width: 50px;
text-align: right;
color: black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<ul id="userList">
</ul>

最新更新