I’m having a problem with D3 joins. I have created some circles on a bubble graph. When the user clicks on a ‘show as map’ button, I want to transform the circles onto a map, then add a label to each one.
Currently the click handler moves the circles OK, then gives me a JavaScript error rather than adding the labels: Uncaught TypeError: Object [object SVGCircleElement]... has no method 'append'. I know this is because my join syntax is incorrect, but how can I fix it?
All the examples I can find of adding new D3 elements are for cases where you’re binding new data – not when you already have existing elements with data already bound.
This is my code for creating the circles:
var circle = g.selectAll('.city')
.data(data).enter()
.append('circle')
.attr('class', 'city')
.attr('r', rfunc).attr("cy", 0)
.attr("cx", function(d, i) {
return rdist(d['dist']);
}).attr("transform", function(d, i) {
return "rotate(" + d.radial_pos + " 0 0)";
});
And this is my click handler:
d3.select("#layout_geo").on("click", function() {
// Move the circles - this works OK.
var circles = d3.selectAll(".city")
.transition()
.duration(1300)
.attr('cx', function(d) {
return merc([d['lon'], d['lat']])[0] - 350;
}).attr('cy', function(d) {
return merc([d['lon'], d['lat']])[1] - 280;
});
// How to add text to each circle?
circles.append('text')
.attr('class', 'background')
.text(function(d) {
console.log(d.name + ', ' + d.city);
return d.name + ', ' + d.city;
})
.attr('cx', function() {
return ???;
}).attr('cy', function() {
return ???;
});
});
The problem here is that the
circlesis not a normal selection but a transition. They have a convenientremove()function to allow for removal of items, but notappendfor adding more elements.Another problem is that appending
<text>elements inside a<circle>attribute is not correct SVG. In this case, you need to put the<text>and the<circle>inside agelement like this. The corresponding change in the code would be:Note that the rotation is lost on the
<circle>element while changing thetransformattribute. It can be preserved by using two nested g elements with rotation on the outer one.