Reputation: 333
I have some problem in d3 v4 when I draw a chord. The question is 'Uncaught TypeError: g_outer.selectAll(...).data(...).enter is not a function' at the 53th in my code. But when I see the source code refering to https://bost.ocks.org/mike/uberdata/ and https://github.com/d3/d3/blob/master/CHANGES.md#chords-d3-chord. I have modified some errors, but it still can't work. Here is my code:
<html>
<head>
<meta charset="UTF-8">
<title>Chord char</title>
</head>
<body>
<script src="http://d3js.org/d3.v4.min.js"></script>
<script>
var city_name = [ "English" , "America" , "German" , "Japan" , "Austrilia" ];
var population = [
[ 1000, 3045, 4567, 1234, 3714 ],
[ 3214, 2000, 2060, 124 , 3234 ],
[ 8761, 6545, 3000, 8045, 647 ],
[ 3211, 1067, 3214, 4000, 1006 ],
[ 2146, 1034, 6745, 4764, 5000 ],
];
var chord_layout = d3.chord(population)
.padAngle(0.03)
.sortSubgroups(d3.descending);
var groups = chord_layout.sortGroups();
var chords = chord_layout.sortChords();
var width = 600;
var height = 600;
var innerRadius = width/2 * 0.7;
var outerRadius = innerRadius * 1.1;
var color20 = d3.scaleOrdinal(d3.schemeCategory20);
//add element
var svg = d3.select("body")
.append("svg")
.attr("width",width)
.attr("height",height)
.append("g")
.attr("transform", "translate(" + width/2 + "," + height/2 + ")");
//draw nodes
var outer_arc = d3.arc()
.innerRadius(innerRadius)
.outerRadius(outerRadius);
var g_outer = svg.append("g");
//add color
g_outer.selectAll("path")
.data(groups)
.enter().append("path")
.style("fill", function(d) { return color20(d.index); })
.style("stroke", function(d) { return color20(d.index); })
.attr("d", outer_arc );
//add text
g_outer.selectAll("text")
.data(groups)
.enter()
.append("text")
.each( function(d,i) {
d.angle = (d.startAngle + d.endAngle) / 2; //calculate the average of the start angle and the end angle
d.name = city_name[i]; //assignment for the city
})
.attr("dy", ".35em") //width
.attr("transform", function(d){ //angle
return "rotate(" + (d.angle * 180 / Math.PI ) + ")" +
"translate(0,"+ -1.0*(outerRadius+10) +")" +
( ( d.angle > Math.PI*3/4 && d.angle < Math.PI*5/4 ) ? "rotate(180)" : "");
}) //to spin when the angle between 135 to 225 degrees
.text(function(d){
return d.name;
})
//add chord
var inner_chord = d3.ribbon()
.radius(innerRadius);
svg.append("g")
.attr("class", "chord")
.selectAll("path") //use the path as element
.attr("d", inner_chord) //
.style("fill", function(d) { return color20(d.source.index); })
.style("opacity" ,1)
.on("mouseover", function(d,i){
d3.select(this)
.style("fill","yellow");
})
.on("mouseout", function(d,i){
d3.select(this)
.transition()
.duration(1000)
.style("fill",color20(d.source.index));
});
</script>
</body>
</html>
I want to draw a chord like this:
But in google chrome, the chord can not appear. I am new to d3, can you help me? I will appreciate it if you give me a good idea! Thankyou!
Upvotes: 0
Views: 757
Reputation: 108567
You have a slew of mistakes in your code. The biggest this that you aren't understanding how d3.chord
function works. The general flow in d3
is to set-up your layout function before giving it any data. In your case like this:
var chord_layout = d3.chord()
.padAngle(0.03)
.sortSubgroups(d3.descending);
var groups = chord_layout(population);
After fixing that, I blended this example with your code to produce:
<html>
<head>
<meta charset="UTF-8">
<title>Chord char</title>
</head>
<body>
<script src="http://d3js.org/d3.v4.min.js"></script>
<script>
var city_name = ["English", "America", "German", "Japan", "Austrilia"];
var population = [
[1000, 3045, 4567, 1234, 3714],
[3214, 2000, 2060, 124, 3234],
[8761, 6545, 3000, 8045, 647],
[3211, 1067, 3214, 4000, 1006],
[2146, 1034, 6745, 4764, 5000],
];
var chord_layout = d3.chord()
.padAngle(0.03)
.sortSubgroups(d3.descending);
var width = 600;
var height = 600;
var innerRadius = width / 2 * 0.7;
var outerRadius = innerRadius * 1.1;
var color20 = d3.scaleOrdinal(d3.schemeCategory20);
//add element
var svg = d3.select("body")
.append("svg")
.attr("width", width)
.attr("height", height);
//draw nodes
var outer_arc = d3.arc()
.innerRadius(innerRadius)
.outerRadius(outerRadius);
var groups = chord_layout(population);
var g_outer = svg.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")")
.datum(groups);
var group = g_outer.append("g")
.attr("class", "groups")
.selectAll("g")
.data(function(chords) { return chords.groups; })
.enter().append("g");
//add color
group.append("path")
.style("fill", function(d) {
return color20(d.index);
})
.style("stroke", function(d) {
return color20(d.index);
})
.attr("d", outer_arc);
//add text
group.append("text")
.attr("dy", ".35em") //width
.attr("transform", function(d,i) { //angle
d.angle = (d.startAngle + d.endAngle) / 2; //calculate the average of the start angle and the end angle
d.name = city_name[i]; //assignment for the city
return "rotate(" + (d.angle * 180 / Math.PI) + ")" +
"translate(0," + -1.0 * (outerRadius + 10) + ")" +
((d.angle > Math.PI * 3 / 4 && d.angle < Math.PI * 5 / 4) ? "rotate(180)" : "");
}) //to spin when the angle between 135 to 225 degrees
.text(function(d) {
return d.name;
});
//add chord
var inner_chord = d3.ribbon()
.radius(innerRadius);
g_outer.append("g")
.attr("class", "ribbons")
.selectAll("path")
.data(function(chords) { return chords; })
.enter().append("path")
.attr("d", inner_chord)
.style("fill", function(d) {
return color20(d.source.index);
})
.style("stroke", "black")
.style("opacity", 0.6)
.on("mouseover", function(d, i) {
d3.select(this)
.style("fill", "yellow");
})
.on("mouseout", function(d, i) {
d3.select(this)
.transition()
.duration(1000)
.style("fill", color20(d.source.index));
});
</script>
</body>
</html>
Upvotes: 2