Skip to content

Instantly share code, notes, and snippets.

@kenpenn
Last active July 27, 2016 02:55
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kenpenn/b48f58ee59ba8088b5c58c2ecc33a8a9 to your computer and use it in GitHub Desktop.
Save kenpenn/b48f58ee59ba8088b5c58c2ecc33a8a9 to your computer and use it in GitHub Desktop.
d3 v4 set datum
license: gpl-3.0

Using d3 v4 to set and use .datum() on elements

With d3 v3, when you set .datum() on an element created from blah.selectAll("blahblah").enter(),

the datum is bound to the element, and can be used later.

With d3 v4, when you set .datum() on an element created from blah.selectAll("blahblah").enter(),

the element is bound to the .data() of the .enter(), and any .datum() you set cannot be used later,

unless you create a new selection that's not bound to the data.

Clicking the right button will toggle between the d3 v3 way of setting datum and the d3 v4 way.

The difference is that the d3 v4 way requires an extra circleG.selectAll('circle')

Compare this example to d3 v3 set datum.

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>d3 v4 set datum</title>
<!-- https://gist.github.com/kenpenn/b48f58ee59ba8088b5c58c2ecc33a8a9 -->
<style>
* { box-sizing: border-box; }
body {
font-size: 16px;
font-family: sans-serif;
margin: 0;
}
.btn { cursor: pointer; }
</style>
</head>
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.1.1/d3.min.js"></script>
<script>
var width = 960;
var height = 500;
var svg = d3.select('body').append('svg').attr('width', width).attr('height', height);
var btnSwitch = svg.append('g').attr('class', 'btn').attr('transform', 'translate(10,10)');
var btnSwitchBg = btnSwitch.append('rect')
.attr('width', 342).attr('height', 44).attr('rx', 3).attr('ry', 3).attr('fill', '#eee').attr('stroke', '#ddd');
var btnSwitchTxt = btnSwitch.append('text').attr('x', 171).attr('y', 26).attr('text-anchor', 'middle');
btnSwitchTxt.text('switching colors on new selection (works)');
var colors = ['hsl(341, 100%, 50%)', 'hsl(127, 100%, 50%)', 'hsl(242, 100%, 50%)'];
var circleG = svg.append('g').attr('transform', 'translate(0,64)');
var slots = colors.length + 1;
var spacing = width / slots;
var rad = 100;
var circles = circleG.selectAll('circle')
.data(colors);
circles.enter()
.append('circle')
.attr('cx', function(d,i) { return (i + 1) * spacing })
.attr('cy', rad)
.attr('r', rad)
.attr('fill', function(d) { return d })
.datum(function (d, i) { return { color: d, idx: i }; } );
btnSwitch.on('click', function () {
var btnCircles = getSelectAll ? circleG.selectAll('circle') : circles;
btnCircles.each(function () {
nextColor(d3.select(this));
});
});
function nextColor (circle) {
var nextIdx = circle.datum().idx + 1 >= colors.length ? 0: circle.datum().idx + 1;
var next = this.colors[nextIdx];
circle
.attr('fill', next)
.datum({ color: next, idx: nextIdx });
}
var getSelectAll = true;
var btnSelect = svg.append('g').attr('class', 'btn').attr('transform', 'translate(362,10)');
var btnSelectBg = btnSelect.append('rect')
.attr('width', 324).attr('height', 44).attr('rx', 3).attr('ry', 3).attr('fill', '#eee').attr('stroke', '#ddd');
var btnSelect = btnSelect.append('text').attr('x', 162).attr('y', 26).attr('text-anchor', 'middle');
btnSelect.text('v4 - using new selection for circles');
btnSelect.on('click', function () {
if (getSelectAll) {
btnSwitchTxt.text('switch colors like d3 v3 (silent fail)');
btnSelect.text('v3 - using var circles from circles.enter()');
} else {
btnSwitchTxt.text('switching colors on new selection (works)');
btnSelect.text('v4 - using new selection for circles');
}
getSelectAll = !getSelectAll;
});
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment