[D3] Better Code Organization with selection.call() with D3 v4
Most of D3’s native selection APIs also return the selection (or a new selection), to enable multiple method calls to be chained together. Since the code you write isn’t on the selection prototype, chaining your methods would take some extra work. selection.call()
will call any function reference you give it, providing the selection as the first parameter, and then it returns the selection for you to ensure chaining is supported.
var scores = [ { name: 'Alice', score: 96 }, { name: 'Billy', score: 83 }, { name: 'Cindy', score: 91 }, { name: 'David', score: 96 }, { name: 'Emily', score: 88 } ]; var bar = d3.select('.chart') .append('svg') .attr('width', 225) .attr('height', 300) .selectAll('g') .data(scores) .enter() .append('g') .attr('transform', (d, i) => 'translate(0, ' + i * 33 + ')'); function scaleBar (selection, scale) { selection.style('transform', 'scaleX(' + scale + ')'); } function setFill (selection, color) { selection.style('fill', color); } function fade (selection, opacity) { selection.style('fill-opacity', opacity); } bar.append('rect') .style('width', d => d.score) .attr('class', 'bar') .on('mouseover', function (d, i, elements) { d3.select(this) .call(scaleBar, 2) .call(setFill, 'orange'); d3.selectAll(elements) .filter(':not(:hover)') .call(fade, 0.5); }) .on('mouseout', function (d, i, elements) { d3.select(this) .call(scaleBar, 1) .call(setFill, 'lightgreen'); d3.selectAll(elements) .call(fade, 1); }); bar.append('text') .attr('y', 20) .text(function (d) { return d.name; });