How to set multiple attributes with one value function?

ericsoco picture ericsoco · Dec 29, 2013 · Viewed 28.4k times · Source

Given a datum containing multiple data elements, such as an object or array, is it possible to set multiple attributes on a selection with a single value function?

E.g. something like:

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];
    });

instead of:

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;
    });

Answer

meetamit picture meetamit · Dec 29, 2013

UPDATE (July 8th 2016) This answer applies to d3 v3.x — NOT v4.x. For the latter version, see Tim Hayes's answer, also on this page. Or... just swap attr with attrs in my answer below, and don't forget to require/import/script-embed d3-selection-multi. And... don't miss the bit about using .each, which may be useful to you.


Yeah, it's possible by passing in a hash (like jQuery's css() method):

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; }
  });

This works for style() as well.

If the reoccurring function (d) {} start to feel like too much, this is another approach:

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
    });
  })

NOTE: this feature only exists in d3.js v2.10.0 or higher