如何用一个值函数设置多个属性?

IT技术 javascript d3.js attributes
2021-02-20 06:13:13

给定包含多个数据元素的数据,例如对象或数组,是否可以使用单个值函数在选择上设置多个属性?

例如:

var data = [{ 'x': 10, 'y': 20, 'r': 5 }];
d3.select('body').append('svg').selectAll('circle')
    .data(data)
    .enter().append('circle')
    .attr('cx cy r', function (d) {
        return [d.x, d.y, d.r];
    });

代替:

var data = [{ 'x': 10, 'y': 20, 'r': 5 }];
d3.select('body').append('svg').selectAll('circle')
    .data(data)
    .enter().append('circle')
    .attr('cx', function (d) {
        return d.x;
    });
    .attr('cy', function (d) {
        return d.y;
    });
    .attr('r', function (d) {
        return d.r;
    });
2个回答

更新(2016 年 7 月 8 日)此答案适用于 d3 v3.x — 不适用于 v4.x。对于后一个版本,请参阅Tim Hayes 的回答,也在此页面上。或者只进行交换attrattrs下面我的回答,并没有忘记要求/进口/脚本嵌入d3-selection-multi并且...不要错过有关 using 的部分.each,它可能对您有用。


是的,可以通过传入散列(如 jQuery 的css()方法)来实现:

d3.select('body').append('svg').selectAll('circle')
  .data(data)
.enter().append('circle')
  .attr({
    cx: function (d) { return d.x; },
    cy: function (d) { return d.y; },
    r:  function (d) { return d.r; }
  });

这也适用style()

如果反复出现function (d) {}感觉太多,这是另一种方法:

d3.select('body').append('svg').selectAll('circle')
  .data(data)
  .enter().append('circle')
  .each(function (d) {
    d3.select(this).attr({
      cx: d.x,
      cy: d.y,
      r:  d.r
    });
  })

注意:此功能仅存在于 d3.js v2.10.0 或更高版本

我问有两个原因:一,能够编写更简洁的代码,二,尽量减少函数调用。您提供的第一个语法很方便,但第二个更接近我正在寻找的 - 每个节点的一个函数调用。有什么方法可以避免包装this在 d3 选择器中并仍然设置属性?(我想我可以只使用本机 JS,但这已经非常接近于为了性能而牺牲易读性。)
2021-04-19 06:13:13
无法跳过thisafaik的包装我也曾经忙于优化,但现在我试着放松一下,因为这通常不是问题。仍然......正如您所指出的,您可以使用本机 JS,并且可能使用抽象的东西以提高可读性。.each(function (d) { applyAttr(this, { cx: d.x, cy: dy, r: d.r }); })其中的执行applyAttr,如果你愿意可以使用本机JS。或者,如果 data 和 dom 元素之间存在一对一的关系,您可以将包装的内容缓存d3.select(this)为 of 的属性d,以避免在后续刷新中重新包装。
2021-04-22 06:13:13
顺便说一句,最后一条评论的抽象也可以看起来像这样: .each( applyAttr(function (d) { return { cx: d.x, cy: dy, r: d.r }; })
2021-04-23 06:13:13
@ericsoco 回复:减少函数调用。d3-selection-multi文档.attrs将其描述为"A convenience method on top of selection.attr for setting multiple attributes."查看源代码确认它只是.attr在循环中调用
2021-05-05 06:13:13

这是一篇旧帖子,但我在谷歌搜索时找到了答案。接受的答案不再适用于 D3 v4.0。

继续前进,您可以使用该attrs()方法执行相同的操作attrs()仅当您加载可选的d3-selection-multi脚本时才受支持

所以使用上面的例子,它在 D3 v4.0 中看起来像这样:

// load d3-selection-multi as separate script
<script src="https://d3js.org/d3-selection-multi.v0.4.min.js"></script>

d3.select('body').append('svg').selectAll('circle')
  .data(data)
  .enter().append('circle')
  .attrs({
    cx: function (d) { return d.x; },
    cy: function (d) { return d.y; },
    r:  function (d) { return d.r; }
  });
如果您可以版本接受答案会很好,对吗?感谢您添加此内容。
2021-04-26 06:13:13
见的最后一段4.0版本说明...the multi-value methods—where you pass an object to set multiple attributes, styles or properties simultaneously—have been extracted to d3-selection-multi and are no longer part of the default bundle. The multi-value map methods have also been renamed to plural form to reduce overload...d3-selection-multi笔记状态:the single-value methods such as selection.attr are recommended for most users, as there is little benefit to the shorter syntax...
2021-05-03 06:13:13
很好的参考@brichins - “......几乎没有好处......”太主观了。一个巨大的好处是能够将属性视为一个对象并将其传递给attrD3 版本 3 中的多个调用——奇怪的是,他们对此采取了如此强硬的立场。
2021-05-07 06:13:13
对于那些希望将样式传递给多个attr()调用的人,您也可以这样做,例如, svg.append("style").text("text {font-family: sans-serif;}");
2021-05-16 06:13:13