D3.js Chord Diagram - Make chords touch the pulled apart arc
up vote
2
down vote
favorite
D3 and Javascript newbie here. I am making a chord diagram with one arc that is pulled apart from the center. I have managed to move the arc into my desire position but I wonder how do I make the group of chord touching the arc again and not messing up the position of other groups of chords?
Here is an image to explain my desired result.
I am currently using an if statement to select the angle where arc C is staying and translate its position.
.attr("transform", function(d) {
if (d.startAngle > Math.PI*1/2 && d.startAngle < Math.PI*5/6) {
return "transform", "translate(" + pullOutSize + "," + pullOutSize + ")"}
;})
I am able to translate the position of the chords by using the translate as well.
.attr("transform", "translate(" + 50 + "," + 50 + ")")
.attr("d", path);
However, when I applied the same if statement to it the translate stop working. It seems like the if statement does not met the condition. I wonder what will be the right statement to put into the if statement to help me select the section of chords that I am trying to move.
.attr("transform", function(d) {
if (d.startAngle > Math.PI*1/2 && d.startAngle < Math.PI*5/6) {
return "transform", "translate(" + pullOutSize + "," + pullOutSize + ")"}
;})
Thanks!
javascript d3.js chord-diagram
add a comment |
up vote
2
down vote
favorite
D3 and Javascript newbie here. I am making a chord diagram with one arc that is pulled apart from the center. I have managed to move the arc into my desire position but I wonder how do I make the group of chord touching the arc again and not messing up the position of other groups of chords?
Here is an image to explain my desired result.
I am currently using an if statement to select the angle where arc C is staying and translate its position.
.attr("transform", function(d) {
if (d.startAngle > Math.PI*1/2 && d.startAngle < Math.PI*5/6) {
return "transform", "translate(" + pullOutSize + "," + pullOutSize + ")"}
;})
I am able to translate the position of the chords by using the translate as well.
.attr("transform", "translate(" + 50 + "," + 50 + ")")
.attr("d", path);
However, when I applied the same if statement to it the translate stop working. It seems like the if statement does not met the condition. I wonder what will be the right statement to put into the if statement to help me select the section of chords that I am trying to move.
.attr("transform", function(d) {
if (d.startAngle > Math.PI*1/2 && d.startAngle < Math.PI*5/6) {
return "transform", "translate(" + pullOutSize + "," + pullOutSize + ")"}
;})
Thanks!
javascript d3.js chord-diagram
with exact the same method as you pulled the arc apart
– rioV8
Nov 11 at 9:54
add a comment |
up vote
2
down vote
favorite
up vote
2
down vote
favorite
D3 and Javascript newbie here. I am making a chord diagram with one arc that is pulled apart from the center. I have managed to move the arc into my desire position but I wonder how do I make the group of chord touching the arc again and not messing up the position of other groups of chords?
Here is an image to explain my desired result.
I am currently using an if statement to select the angle where arc C is staying and translate its position.
.attr("transform", function(d) {
if (d.startAngle > Math.PI*1/2 && d.startAngle < Math.PI*5/6) {
return "transform", "translate(" + pullOutSize + "," + pullOutSize + ")"}
;})
I am able to translate the position of the chords by using the translate as well.
.attr("transform", "translate(" + 50 + "," + 50 + ")")
.attr("d", path);
However, when I applied the same if statement to it the translate stop working. It seems like the if statement does not met the condition. I wonder what will be the right statement to put into the if statement to help me select the section of chords that I am trying to move.
.attr("transform", function(d) {
if (d.startAngle > Math.PI*1/2 && d.startAngle < Math.PI*5/6) {
return "transform", "translate(" + pullOutSize + "," + pullOutSize + ")"}
;})
Thanks!
javascript d3.js chord-diagram
D3 and Javascript newbie here. I am making a chord diagram with one arc that is pulled apart from the center. I have managed to move the arc into my desire position but I wonder how do I make the group of chord touching the arc again and not messing up the position of other groups of chords?
Here is an image to explain my desired result.
I am currently using an if statement to select the angle where arc C is staying and translate its position.
.attr("transform", function(d) {
if (d.startAngle > Math.PI*1/2 && d.startAngle < Math.PI*5/6) {
return "transform", "translate(" + pullOutSize + "," + pullOutSize + ")"}
;})
I am able to translate the position of the chords by using the translate as well.
.attr("transform", "translate(" + 50 + "," + 50 + ")")
.attr("d", path);
However, when I applied the same if statement to it the translate stop working. It seems like the if statement does not met the condition. I wonder what will be the right statement to put into the if statement to help me select the section of chords that I am trying to move.
.attr("transform", function(d) {
if (d.startAngle > Math.PI*1/2 && d.startAngle < Math.PI*5/6) {
return "transform", "translate(" + pullOutSize + "," + pullOutSize + ")"}
;})
Thanks!
javascript d3.js chord-diagram
javascript d3.js chord-diagram
edited Nov 11 at 11:01
asked Nov 11 at 8:36
Popo.J
112
112
with exact the same method as you pulled the arc apart
– rioV8
Nov 11 at 9:54
add a comment |
with exact the same method as you pulled the arc apart
– rioV8
Nov 11 at 9:54
with exact the same method as you pulled the arc apart
– rioV8
Nov 11 at 9:54
with exact the same method as you pulled the arc apart
– rioV8
Nov 11 at 9:54
add a comment |
1 Answer
1
active
oldest
votes
up vote
1
down vote
According to the documentation, you can pass the radius as a parameter when creating the chord/ribbon.
Documentation for ribbon
// from documentation
var ribbon = d3.ribbon();
ribbon({
source: {startAngle: 0.7524114, endAngle: 1.1212972, radius: 240},
target: {startAngle: 1.8617078, endAngle: 1.9842927, radius: 240}
});
<!DOCTYPE html>
<meta charset="utf-8">
<style>
body {
font: 20px sans-serif;
}
.group-tick line {
stroke: #000;
}
.ribbons {
fill-opacity: 0.67;
}
</style>
<svg width="800" height="800">
<defs>
<linearGradient id="Gradient1">
<stop class="stop1" offset="0%"/>
<stop class="stop2" offset="50%"/>
<stop class="stop3" offset="100%"/>
</linearGradient>
<linearGradient id="Gradient2" x1="0" x2="0" y1="0" y2="1">
<stop offset="0%" stop-color="red"/>
<stop offset="50%" stop-color="black" stop-opacity="0"/>
<stop offset="100%" stop-color="blue"/>
</linearGradient>
</defs>
</svg>
<script src="https://d3js.org/d3.v5.min.js"></script>
<script>
var matrixData={
"Occupants":
[0, 10,10,10,10,0,0,0,10,10,10,10,10],
"Flooring":
[70,0,0,0,0,0,30,0,0,0,0,0,0],
"Millwork":
[40, 0,0,0,0,0,60,0,0,0,0,0],
"Ceilings":
[60, 0,0,0,0,0,40,0,0,0,0,0,0],
"Wet Applied Products":
[60, 0,0,0,0,0,40,0,0,0,0,0,0],
"Curtain Wall":
[0, 0,0,0,0,0,100,0,0,0,0,0,0],
"Environment":
[0, 10,10,10,10,0,10,0,10,10,10,0,10],
"Roofing":
[0, 0,0,0,0,0,80,0,0,0,0,0],
"Insulation":
[50, 0,0,0,0,0,50,0,0,0,0,0,0],
"MEPFP":
[40, 0,0,0,0,0,60,0,0,0,0,0,0],
"Structure":
[50, 0,0,0,0,0,50,0,0,0,0,0,0],
"Furniture":
[90, 0,0,0,0,0,10,0,0,0,0,0,0]
}
matrix= Object.values(matrixData);
matrixKeys = Object.keys(matrixData);
var svg = d3.select("svg"),
width = +svg.attr("width"),
height = +svg.attr("height"),
outerRadius = Math.min(width, height) * 0.5 - 150,
innerRadius = outerRadius - 30;
var formatValue = d3.formatPrefix(",.0", 1e3);
var chord = d3.chord()
.padAngle(0.024)
.sortSubgroups(d3.descending);
var arc = d3.arc()
.innerRadius(innerRadius)
.outerRadius(outerRadius);
var ribbon = d3.ribbon();
var color = d3.scaleOrdinal()
.domain(d3.range(4))
.range(["#6FCDE3",
"#D7DAE5",
"#D7DAE5",
"#D7DAE5",
"#D7DAE5",
"#D7DAE5",
"#E5E52B",
"#D7DAE5",
"#D7DAE5",
"#D7DAE5",
"#D7DAE5",
"#D7DAE5"
]);
var g = svg.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ") rotate(75)")
.datum(chord(matrix));
var group = g.append("g")
.attr("class", "groups")
.selectAll("g")
.data(function(chords) { return chords.groups; })
.enter().append("g");
group.append("path")
.style("fill", function(d) { return color(d.index); })
.style("stroke", function(d) { return d3.rgb(color(d.index)).darker(); })
.attr("d", function(d,i) {
var radius = 0;
if(d.index%2 != 0) radius = 50;
return arc.innerRadius(innerRadius + radius)
.outerRadius(outerRadius + radius)(d);}).on("mouseover", function(d,i) {
fade(.1,d);
})
.on("mouseout", function(d,i) {
fade(1,d);
});
var groupTick = group.selectAll(".group-tick")
.data(function(d) { return groupTicks(d, 1e3); })
.enter().append("g")
.attr("class", "group-tick")
.attr("transform", function(d) {
var radius = 0;
if(d.index%2 != 0) radius = 50;
return "rotate(" + (d.angle * 180 / Math.PI - 75) +
") translate(" + (outerRadius + radius) + ",2)";
});
groupTick.append("line")
.attr("x2", 6);
groupTick
.filter(function(d) { return d.value % 5e3 === 0; })
.append("text")
.attr("x", 8)
.attr("dy", ".35em")
.attr("transform", function(d) { return d.angle > Math.PI/2 && d.angle < Math.PI*3/2 ? "rotate(180) translate(-16)" : null; })
.style("text-anchor", function(d) { return d.angle > Math.PI/2 && d.angle < Math.PI*3/2? "end" : null; })
.text(function(d) {
return matrixKeys[d.index];
});
g.append("g")
.attr("class", "ribbons")
.selectAll("path")
.data(function(chords) {
return chords; })
.enter().append("path")
.attr("d", function(d) {
if(d.source.index%2 == 0) d.source.radius = innerRadius;
else d.source.radius = innerRadius + 50;
if(d.target.index%2 == 0) d.target.radius = innerRadius;
else d.target.radius = innerRadius + 50;
return ribbon(d);
})
.attr("class", function(d,i) { return matrixKeys[d.index]})
.style("fill", function(d) { return color(d.target.index); })
.style("stroke", function(d) { return d3.rgb(color(d.target.index)).darker(); });
// Returns an array of tick angles and values for a given group and step.
function groupTicks(d, step) {
var k = (d.endAngle - d.startAngle) / d.value;
return d3.range(0, d.value, step).map(function(value) {
return {
index:d.index,
value: value,
angle: value * k + d.startAngle
};
});
}
function fade(opacity, d2) {
var hightLight = g.selectAll(".ribbons path").filter(function(d) {
return d.source.index != d2.index && d.target.index != d2.index;
});
hightLight.transition()
.style("opacity", opacity);
}
</script>
add a comment |
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
1
down vote
According to the documentation, you can pass the radius as a parameter when creating the chord/ribbon.
Documentation for ribbon
// from documentation
var ribbon = d3.ribbon();
ribbon({
source: {startAngle: 0.7524114, endAngle: 1.1212972, radius: 240},
target: {startAngle: 1.8617078, endAngle: 1.9842927, radius: 240}
});
<!DOCTYPE html>
<meta charset="utf-8">
<style>
body {
font: 20px sans-serif;
}
.group-tick line {
stroke: #000;
}
.ribbons {
fill-opacity: 0.67;
}
</style>
<svg width="800" height="800">
<defs>
<linearGradient id="Gradient1">
<stop class="stop1" offset="0%"/>
<stop class="stop2" offset="50%"/>
<stop class="stop3" offset="100%"/>
</linearGradient>
<linearGradient id="Gradient2" x1="0" x2="0" y1="0" y2="1">
<stop offset="0%" stop-color="red"/>
<stop offset="50%" stop-color="black" stop-opacity="0"/>
<stop offset="100%" stop-color="blue"/>
</linearGradient>
</defs>
</svg>
<script src="https://d3js.org/d3.v5.min.js"></script>
<script>
var matrixData={
"Occupants":
[0, 10,10,10,10,0,0,0,10,10,10,10,10],
"Flooring":
[70,0,0,0,0,0,30,0,0,0,0,0,0],
"Millwork":
[40, 0,0,0,0,0,60,0,0,0,0,0],
"Ceilings":
[60, 0,0,0,0,0,40,0,0,0,0,0,0],
"Wet Applied Products":
[60, 0,0,0,0,0,40,0,0,0,0,0,0],
"Curtain Wall":
[0, 0,0,0,0,0,100,0,0,0,0,0,0],
"Environment":
[0, 10,10,10,10,0,10,0,10,10,10,0,10],
"Roofing":
[0, 0,0,0,0,0,80,0,0,0,0,0],
"Insulation":
[50, 0,0,0,0,0,50,0,0,0,0,0,0],
"MEPFP":
[40, 0,0,0,0,0,60,0,0,0,0,0,0],
"Structure":
[50, 0,0,0,0,0,50,0,0,0,0,0,0],
"Furniture":
[90, 0,0,0,0,0,10,0,0,0,0,0,0]
}
matrix= Object.values(matrixData);
matrixKeys = Object.keys(matrixData);
var svg = d3.select("svg"),
width = +svg.attr("width"),
height = +svg.attr("height"),
outerRadius = Math.min(width, height) * 0.5 - 150,
innerRadius = outerRadius - 30;
var formatValue = d3.formatPrefix(",.0", 1e3);
var chord = d3.chord()
.padAngle(0.024)
.sortSubgroups(d3.descending);
var arc = d3.arc()
.innerRadius(innerRadius)
.outerRadius(outerRadius);
var ribbon = d3.ribbon();
var color = d3.scaleOrdinal()
.domain(d3.range(4))
.range(["#6FCDE3",
"#D7DAE5",
"#D7DAE5",
"#D7DAE5",
"#D7DAE5",
"#D7DAE5",
"#E5E52B",
"#D7DAE5",
"#D7DAE5",
"#D7DAE5",
"#D7DAE5",
"#D7DAE5"
]);
var g = svg.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ") rotate(75)")
.datum(chord(matrix));
var group = g.append("g")
.attr("class", "groups")
.selectAll("g")
.data(function(chords) { return chords.groups; })
.enter().append("g");
group.append("path")
.style("fill", function(d) { return color(d.index); })
.style("stroke", function(d) { return d3.rgb(color(d.index)).darker(); })
.attr("d", function(d,i) {
var radius = 0;
if(d.index%2 != 0) radius = 50;
return arc.innerRadius(innerRadius + radius)
.outerRadius(outerRadius + radius)(d);}).on("mouseover", function(d,i) {
fade(.1,d);
})
.on("mouseout", function(d,i) {
fade(1,d);
});
var groupTick = group.selectAll(".group-tick")
.data(function(d) { return groupTicks(d, 1e3); })
.enter().append("g")
.attr("class", "group-tick")
.attr("transform", function(d) {
var radius = 0;
if(d.index%2 != 0) radius = 50;
return "rotate(" + (d.angle * 180 / Math.PI - 75) +
") translate(" + (outerRadius + radius) + ",2)";
});
groupTick.append("line")
.attr("x2", 6);
groupTick
.filter(function(d) { return d.value % 5e3 === 0; })
.append("text")
.attr("x", 8)
.attr("dy", ".35em")
.attr("transform", function(d) { return d.angle > Math.PI/2 && d.angle < Math.PI*3/2 ? "rotate(180) translate(-16)" : null; })
.style("text-anchor", function(d) { return d.angle > Math.PI/2 && d.angle < Math.PI*3/2? "end" : null; })
.text(function(d) {
return matrixKeys[d.index];
});
g.append("g")
.attr("class", "ribbons")
.selectAll("path")
.data(function(chords) {
return chords; })
.enter().append("path")
.attr("d", function(d) {
if(d.source.index%2 == 0) d.source.radius = innerRadius;
else d.source.radius = innerRadius + 50;
if(d.target.index%2 == 0) d.target.radius = innerRadius;
else d.target.radius = innerRadius + 50;
return ribbon(d);
})
.attr("class", function(d,i) { return matrixKeys[d.index]})
.style("fill", function(d) { return color(d.target.index); })
.style("stroke", function(d) { return d3.rgb(color(d.target.index)).darker(); });
// Returns an array of tick angles and values for a given group and step.
function groupTicks(d, step) {
var k = (d.endAngle - d.startAngle) / d.value;
return d3.range(0, d.value, step).map(function(value) {
return {
index:d.index,
value: value,
angle: value * k + d.startAngle
};
});
}
function fade(opacity, d2) {
var hightLight = g.selectAll(".ribbons path").filter(function(d) {
return d.source.index != d2.index && d.target.index != d2.index;
});
hightLight.transition()
.style("opacity", opacity);
}
</script>
add a comment |
up vote
1
down vote
According to the documentation, you can pass the radius as a parameter when creating the chord/ribbon.
Documentation for ribbon
// from documentation
var ribbon = d3.ribbon();
ribbon({
source: {startAngle: 0.7524114, endAngle: 1.1212972, radius: 240},
target: {startAngle: 1.8617078, endAngle: 1.9842927, radius: 240}
});
<!DOCTYPE html>
<meta charset="utf-8">
<style>
body {
font: 20px sans-serif;
}
.group-tick line {
stroke: #000;
}
.ribbons {
fill-opacity: 0.67;
}
</style>
<svg width="800" height="800">
<defs>
<linearGradient id="Gradient1">
<stop class="stop1" offset="0%"/>
<stop class="stop2" offset="50%"/>
<stop class="stop3" offset="100%"/>
</linearGradient>
<linearGradient id="Gradient2" x1="0" x2="0" y1="0" y2="1">
<stop offset="0%" stop-color="red"/>
<stop offset="50%" stop-color="black" stop-opacity="0"/>
<stop offset="100%" stop-color="blue"/>
</linearGradient>
</defs>
</svg>
<script src="https://d3js.org/d3.v5.min.js"></script>
<script>
var matrixData={
"Occupants":
[0, 10,10,10,10,0,0,0,10,10,10,10,10],
"Flooring":
[70,0,0,0,0,0,30,0,0,0,0,0,0],
"Millwork":
[40, 0,0,0,0,0,60,0,0,0,0,0],
"Ceilings":
[60, 0,0,0,0,0,40,0,0,0,0,0,0],
"Wet Applied Products":
[60, 0,0,0,0,0,40,0,0,0,0,0,0],
"Curtain Wall":
[0, 0,0,0,0,0,100,0,0,0,0,0,0],
"Environment":
[0, 10,10,10,10,0,10,0,10,10,10,0,10],
"Roofing":
[0, 0,0,0,0,0,80,0,0,0,0,0],
"Insulation":
[50, 0,0,0,0,0,50,0,0,0,0,0,0],
"MEPFP":
[40, 0,0,0,0,0,60,0,0,0,0,0,0],
"Structure":
[50, 0,0,0,0,0,50,0,0,0,0,0,0],
"Furniture":
[90, 0,0,0,0,0,10,0,0,0,0,0,0]
}
matrix= Object.values(matrixData);
matrixKeys = Object.keys(matrixData);
var svg = d3.select("svg"),
width = +svg.attr("width"),
height = +svg.attr("height"),
outerRadius = Math.min(width, height) * 0.5 - 150,
innerRadius = outerRadius - 30;
var formatValue = d3.formatPrefix(",.0", 1e3);
var chord = d3.chord()
.padAngle(0.024)
.sortSubgroups(d3.descending);
var arc = d3.arc()
.innerRadius(innerRadius)
.outerRadius(outerRadius);
var ribbon = d3.ribbon();
var color = d3.scaleOrdinal()
.domain(d3.range(4))
.range(["#6FCDE3",
"#D7DAE5",
"#D7DAE5",
"#D7DAE5",
"#D7DAE5",
"#D7DAE5",
"#E5E52B",
"#D7DAE5",
"#D7DAE5",
"#D7DAE5",
"#D7DAE5",
"#D7DAE5"
]);
var g = svg.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ") rotate(75)")
.datum(chord(matrix));
var group = g.append("g")
.attr("class", "groups")
.selectAll("g")
.data(function(chords) { return chords.groups; })
.enter().append("g");
group.append("path")
.style("fill", function(d) { return color(d.index); })
.style("stroke", function(d) { return d3.rgb(color(d.index)).darker(); })
.attr("d", function(d,i) {
var radius = 0;
if(d.index%2 != 0) radius = 50;
return arc.innerRadius(innerRadius + radius)
.outerRadius(outerRadius + radius)(d);}).on("mouseover", function(d,i) {
fade(.1,d);
})
.on("mouseout", function(d,i) {
fade(1,d);
});
var groupTick = group.selectAll(".group-tick")
.data(function(d) { return groupTicks(d, 1e3); })
.enter().append("g")
.attr("class", "group-tick")
.attr("transform", function(d) {
var radius = 0;
if(d.index%2 != 0) radius = 50;
return "rotate(" + (d.angle * 180 / Math.PI - 75) +
") translate(" + (outerRadius + radius) + ",2)";
});
groupTick.append("line")
.attr("x2", 6);
groupTick
.filter(function(d) { return d.value % 5e3 === 0; })
.append("text")
.attr("x", 8)
.attr("dy", ".35em")
.attr("transform", function(d) { return d.angle > Math.PI/2 && d.angle < Math.PI*3/2 ? "rotate(180) translate(-16)" : null; })
.style("text-anchor", function(d) { return d.angle > Math.PI/2 && d.angle < Math.PI*3/2? "end" : null; })
.text(function(d) {
return matrixKeys[d.index];
});
g.append("g")
.attr("class", "ribbons")
.selectAll("path")
.data(function(chords) {
return chords; })
.enter().append("path")
.attr("d", function(d) {
if(d.source.index%2 == 0) d.source.radius = innerRadius;
else d.source.radius = innerRadius + 50;
if(d.target.index%2 == 0) d.target.radius = innerRadius;
else d.target.radius = innerRadius + 50;
return ribbon(d);
})
.attr("class", function(d,i) { return matrixKeys[d.index]})
.style("fill", function(d) { return color(d.target.index); })
.style("stroke", function(d) { return d3.rgb(color(d.target.index)).darker(); });
// Returns an array of tick angles and values for a given group and step.
function groupTicks(d, step) {
var k = (d.endAngle - d.startAngle) / d.value;
return d3.range(0, d.value, step).map(function(value) {
return {
index:d.index,
value: value,
angle: value * k + d.startAngle
};
});
}
function fade(opacity, d2) {
var hightLight = g.selectAll(".ribbons path").filter(function(d) {
return d.source.index != d2.index && d.target.index != d2.index;
});
hightLight.transition()
.style("opacity", opacity);
}
</script>
add a comment |
up vote
1
down vote
up vote
1
down vote
According to the documentation, you can pass the radius as a parameter when creating the chord/ribbon.
Documentation for ribbon
// from documentation
var ribbon = d3.ribbon();
ribbon({
source: {startAngle: 0.7524114, endAngle: 1.1212972, radius: 240},
target: {startAngle: 1.8617078, endAngle: 1.9842927, radius: 240}
});
<!DOCTYPE html>
<meta charset="utf-8">
<style>
body {
font: 20px sans-serif;
}
.group-tick line {
stroke: #000;
}
.ribbons {
fill-opacity: 0.67;
}
</style>
<svg width="800" height="800">
<defs>
<linearGradient id="Gradient1">
<stop class="stop1" offset="0%"/>
<stop class="stop2" offset="50%"/>
<stop class="stop3" offset="100%"/>
</linearGradient>
<linearGradient id="Gradient2" x1="0" x2="0" y1="0" y2="1">
<stop offset="0%" stop-color="red"/>
<stop offset="50%" stop-color="black" stop-opacity="0"/>
<stop offset="100%" stop-color="blue"/>
</linearGradient>
</defs>
</svg>
<script src="https://d3js.org/d3.v5.min.js"></script>
<script>
var matrixData={
"Occupants":
[0, 10,10,10,10,0,0,0,10,10,10,10,10],
"Flooring":
[70,0,0,0,0,0,30,0,0,0,0,0,0],
"Millwork":
[40, 0,0,0,0,0,60,0,0,0,0,0],
"Ceilings":
[60, 0,0,0,0,0,40,0,0,0,0,0,0],
"Wet Applied Products":
[60, 0,0,0,0,0,40,0,0,0,0,0,0],
"Curtain Wall":
[0, 0,0,0,0,0,100,0,0,0,0,0,0],
"Environment":
[0, 10,10,10,10,0,10,0,10,10,10,0,10],
"Roofing":
[0, 0,0,0,0,0,80,0,0,0,0,0],
"Insulation":
[50, 0,0,0,0,0,50,0,0,0,0,0,0],
"MEPFP":
[40, 0,0,0,0,0,60,0,0,0,0,0,0],
"Structure":
[50, 0,0,0,0,0,50,0,0,0,0,0,0],
"Furniture":
[90, 0,0,0,0,0,10,0,0,0,0,0,0]
}
matrix= Object.values(matrixData);
matrixKeys = Object.keys(matrixData);
var svg = d3.select("svg"),
width = +svg.attr("width"),
height = +svg.attr("height"),
outerRadius = Math.min(width, height) * 0.5 - 150,
innerRadius = outerRadius - 30;
var formatValue = d3.formatPrefix(",.0", 1e3);
var chord = d3.chord()
.padAngle(0.024)
.sortSubgroups(d3.descending);
var arc = d3.arc()
.innerRadius(innerRadius)
.outerRadius(outerRadius);
var ribbon = d3.ribbon();
var color = d3.scaleOrdinal()
.domain(d3.range(4))
.range(["#6FCDE3",
"#D7DAE5",
"#D7DAE5",
"#D7DAE5",
"#D7DAE5",
"#D7DAE5",
"#E5E52B",
"#D7DAE5",
"#D7DAE5",
"#D7DAE5",
"#D7DAE5",
"#D7DAE5"
]);
var g = svg.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ") rotate(75)")
.datum(chord(matrix));
var group = g.append("g")
.attr("class", "groups")
.selectAll("g")
.data(function(chords) { return chords.groups; })
.enter().append("g");
group.append("path")
.style("fill", function(d) { return color(d.index); })
.style("stroke", function(d) { return d3.rgb(color(d.index)).darker(); })
.attr("d", function(d,i) {
var radius = 0;
if(d.index%2 != 0) radius = 50;
return arc.innerRadius(innerRadius + radius)
.outerRadius(outerRadius + radius)(d);}).on("mouseover", function(d,i) {
fade(.1,d);
})
.on("mouseout", function(d,i) {
fade(1,d);
});
var groupTick = group.selectAll(".group-tick")
.data(function(d) { return groupTicks(d, 1e3); })
.enter().append("g")
.attr("class", "group-tick")
.attr("transform", function(d) {
var radius = 0;
if(d.index%2 != 0) radius = 50;
return "rotate(" + (d.angle * 180 / Math.PI - 75) +
") translate(" + (outerRadius + radius) + ",2)";
});
groupTick.append("line")
.attr("x2", 6);
groupTick
.filter(function(d) { return d.value % 5e3 === 0; })
.append("text")
.attr("x", 8)
.attr("dy", ".35em")
.attr("transform", function(d) { return d.angle > Math.PI/2 && d.angle < Math.PI*3/2 ? "rotate(180) translate(-16)" : null; })
.style("text-anchor", function(d) { return d.angle > Math.PI/2 && d.angle < Math.PI*3/2? "end" : null; })
.text(function(d) {
return matrixKeys[d.index];
});
g.append("g")
.attr("class", "ribbons")
.selectAll("path")
.data(function(chords) {
return chords; })
.enter().append("path")
.attr("d", function(d) {
if(d.source.index%2 == 0) d.source.radius = innerRadius;
else d.source.radius = innerRadius + 50;
if(d.target.index%2 == 0) d.target.radius = innerRadius;
else d.target.radius = innerRadius + 50;
return ribbon(d);
})
.attr("class", function(d,i) { return matrixKeys[d.index]})
.style("fill", function(d) { return color(d.target.index); })
.style("stroke", function(d) { return d3.rgb(color(d.target.index)).darker(); });
// Returns an array of tick angles and values for a given group and step.
function groupTicks(d, step) {
var k = (d.endAngle - d.startAngle) / d.value;
return d3.range(0, d.value, step).map(function(value) {
return {
index:d.index,
value: value,
angle: value * k + d.startAngle
};
});
}
function fade(opacity, d2) {
var hightLight = g.selectAll(".ribbons path").filter(function(d) {
return d.source.index != d2.index && d.target.index != d2.index;
});
hightLight.transition()
.style("opacity", opacity);
}
</script>
According to the documentation, you can pass the radius as a parameter when creating the chord/ribbon.
Documentation for ribbon
// from documentation
var ribbon = d3.ribbon();
ribbon({
source: {startAngle: 0.7524114, endAngle: 1.1212972, radius: 240},
target: {startAngle: 1.8617078, endAngle: 1.9842927, radius: 240}
});
<!DOCTYPE html>
<meta charset="utf-8">
<style>
body {
font: 20px sans-serif;
}
.group-tick line {
stroke: #000;
}
.ribbons {
fill-opacity: 0.67;
}
</style>
<svg width="800" height="800">
<defs>
<linearGradient id="Gradient1">
<stop class="stop1" offset="0%"/>
<stop class="stop2" offset="50%"/>
<stop class="stop3" offset="100%"/>
</linearGradient>
<linearGradient id="Gradient2" x1="0" x2="0" y1="0" y2="1">
<stop offset="0%" stop-color="red"/>
<stop offset="50%" stop-color="black" stop-opacity="0"/>
<stop offset="100%" stop-color="blue"/>
</linearGradient>
</defs>
</svg>
<script src="https://d3js.org/d3.v5.min.js"></script>
<script>
var matrixData={
"Occupants":
[0, 10,10,10,10,0,0,0,10,10,10,10,10],
"Flooring":
[70,0,0,0,0,0,30,0,0,0,0,0,0],
"Millwork":
[40, 0,0,0,0,0,60,0,0,0,0,0],
"Ceilings":
[60, 0,0,0,0,0,40,0,0,0,0,0,0],
"Wet Applied Products":
[60, 0,0,0,0,0,40,0,0,0,0,0,0],
"Curtain Wall":
[0, 0,0,0,0,0,100,0,0,0,0,0,0],
"Environment":
[0, 10,10,10,10,0,10,0,10,10,10,0,10],
"Roofing":
[0, 0,0,0,0,0,80,0,0,0,0,0],
"Insulation":
[50, 0,0,0,0,0,50,0,0,0,0,0,0],
"MEPFP":
[40, 0,0,0,0,0,60,0,0,0,0,0,0],
"Structure":
[50, 0,0,0,0,0,50,0,0,0,0,0,0],
"Furniture":
[90, 0,0,0,0,0,10,0,0,0,0,0,0]
}
matrix= Object.values(matrixData);
matrixKeys = Object.keys(matrixData);
var svg = d3.select("svg"),
width = +svg.attr("width"),
height = +svg.attr("height"),
outerRadius = Math.min(width, height) * 0.5 - 150,
innerRadius = outerRadius - 30;
var formatValue = d3.formatPrefix(",.0", 1e3);
var chord = d3.chord()
.padAngle(0.024)
.sortSubgroups(d3.descending);
var arc = d3.arc()
.innerRadius(innerRadius)
.outerRadius(outerRadius);
var ribbon = d3.ribbon();
var color = d3.scaleOrdinal()
.domain(d3.range(4))
.range(["#6FCDE3",
"#D7DAE5",
"#D7DAE5",
"#D7DAE5",
"#D7DAE5",
"#D7DAE5",
"#E5E52B",
"#D7DAE5",
"#D7DAE5",
"#D7DAE5",
"#D7DAE5",
"#D7DAE5"
]);
var g = svg.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ") rotate(75)")
.datum(chord(matrix));
var group = g.append("g")
.attr("class", "groups")
.selectAll("g")
.data(function(chords) { return chords.groups; })
.enter().append("g");
group.append("path")
.style("fill", function(d) { return color(d.index); })
.style("stroke", function(d) { return d3.rgb(color(d.index)).darker(); })
.attr("d", function(d,i) {
var radius = 0;
if(d.index%2 != 0) radius = 50;
return arc.innerRadius(innerRadius + radius)
.outerRadius(outerRadius + radius)(d);}).on("mouseover", function(d,i) {
fade(.1,d);
})
.on("mouseout", function(d,i) {
fade(1,d);
});
var groupTick = group.selectAll(".group-tick")
.data(function(d) { return groupTicks(d, 1e3); })
.enter().append("g")
.attr("class", "group-tick")
.attr("transform", function(d) {
var radius = 0;
if(d.index%2 != 0) radius = 50;
return "rotate(" + (d.angle * 180 / Math.PI - 75) +
") translate(" + (outerRadius + radius) + ",2)";
});
groupTick.append("line")
.attr("x2", 6);
groupTick
.filter(function(d) { return d.value % 5e3 === 0; })
.append("text")
.attr("x", 8)
.attr("dy", ".35em")
.attr("transform", function(d) { return d.angle > Math.PI/2 && d.angle < Math.PI*3/2 ? "rotate(180) translate(-16)" : null; })
.style("text-anchor", function(d) { return d.angle > Math.PI/2 && d.angle < Math.PI*3/2? "end" : null; })
.text(function(d) {
return matrixKeys[d.index];
});
g.append("g")
.attr("class", "ribbons")
.selectAll("path")
.data(function(chords) {
return chords; })
.enter().append("path")
.attr("d", function(d) {
if(d.source.index%2 == 0) d.source.radius = innerRadius;
else d.source.radius = innerRadius + 50;
if(d.target.index%2 == 0) d.target.radius = innerRadius;
else d.target.radius = innerRadius + 50;
return ribbon(d);
})
.attr("class", function(d,i) { return matrixKeys[d.index]})
.style("fill", function(d) { return color(d.target.index); })
.style("stroke", function(d) { return d3.rgb(color(d.target.index)).darker(); });
// Returns an array of tick angles and values for a given group and step.
function groupTicks(d, step) {
var k = (d.endAngle - d.startAngle) / d.value;
return d3.range(0, d.value, step).map(function(value) {
return {
index:d.index,
value: value,
angle: value * k + d.startAngle
};
});
}
function fade(opacity, d2) {
var hightLight = g.selectAll(".ribbons path").filter(function(d) {
return d.source.index != d2.index && d.target.index != d2.index;
});
hightLight.transition()
.style("opacity", opacity);
}
</script>
<!DOCTYPE html>
<meta charset="utf-8">
<style>
body {
font: 20px sans-serif;
}
.group-tick line {
stroke: #000;
}
.ribbons {
fill-opacity: 0.67;
}
</style>
<svg width="800" height="800">
<defs>
<linearGradient id="Gradient1">
<stop class="stop1" offset="0%"/>
<stop class="stop2" offset="50%"/>
<stop class="stop3" offset="100%"/>
</linearGradient>
<linearGradient id="Gradient2" x1="0" x2="0" y1="0" y2="1">
<stop offset="0%" stop-color="red"/>
<stop offset="50%" stop-color="black" stop-opacity="0"/>
<stop offset="100%" stop-color="blue"/>
</linearGradient>
</defs>
</svg>
<script src="https://d3js.org/d3.v5.min.js"></script>
<script>
var matrixData={
"Occupants":
[0, 10,10,10,10,0,0,0,10,10,10,10,10],
"Flooring":
[70,0,0,0,0,0,30,0,0,0,0,0,0],
"Millwork":
[40, 0,0,0,0,0,60,0,0,0,0,0],
"Ceilings":
[60, 0,0,0,0,0,40,0,0,0,0,0,0],
"Wet Applied Products":
[60, 0,0,0,0,0,40,0,0,0,0,0,0],
"Curtain Wall":
[0, 0,0,0,0,0,100,0,0,0,0,0,0],
"Environment":
[0, 10,10,10,10,0,10,0,10,10,10,0,10],
"Roofing":
[0, 0,0,0,0,0,80,0,0,0,0,0],
"Insulation":
[50, 0,0,0,0,0,50,0,0,0,0,0,0],
"MEPFP":
[40, 0,0,0,0,0,60,0,0,0,0,0,0],
"Structure":
[50, 0,0,0,0,0,50,0,0,0,0,0,0],
"Furniture":
[90, 0,0,0,0,0,10,0,0,0,0,0,0]
}
matrix= Object.values(matrixData);
matrixKeys = Object.keys(matrixData);
var svg = d3.select("svg"),
width = +svg.attr("width"),
height = +svg.attr("height"),
outerRadius = Math.min(width, height) * 0.5 - 150,
innerRadius = outerRadius - 30;
var formatValue = d3.formatPrefix(",.0", 1e3);
var chord = d3.chord()
.padAngle(0.024)
.sortSubgroups(d3.descending);
var arc = d3.arc()
.innerRadius(innerRadius)
.outerRadius(outerRadius);
var ribbon = d3.ribbon();
var color = d3.scaleOrdinal()
.domain(d3.range(4))
.range(["#6FCDE3",
"#D7DAE5",
"#D7DAE5",
"#D7DAE5",
"#D7DAE5",
"#D7DAE5",
"#E5E52B",
"#D7DAE5",
"#D7DAE5",
"#D7DAE5",
"#D7DAE5",
"#D7DAE5"
]);
var g = svg.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ") rotate(75)")
.datum(chord(matrix));
var group = g.append("g")
.attr("class", "groups")
.selectAll("g")
.data(function(chords) { return chords.groups; })
.enter().append("g");
group.append("path")
.style("fill", function(d) { return color(d.index); })
.style("stroke", function(d) { return d3.rgb(color(d.index)).darker(); })
.attr("d", function(d,i) {
var radius = 0;
if(d.index%2 != 0) radius = 50;
return arc.innerRadius(innerRadius + radius)
.outerRadius(outerRadius + radius)(d);}).on("mouseover", function(d,i) {
fade(.1,d);
})
.on("mouseout", function(d,i) {
fade(1,d);
});
var groupTick = group.selectAll(".group-tick")
.data(function(d) { return groupTicks(d, 1e3); })
.enter().append("g")
.attr("class", "group-tick")
.attr("transform", function(d) {
var radius = 0;
if(d.index%2 != 0) radius = 50;
return "rotate(" + (d.angle * 180 / Math.PI - 75) +
") translate(" + (outerRadius + radius) + ",2)";
});
groupTick.append("line")
.attr("x2", 6);
groupTick
.filter(function(d) { return d.value % 5e3 === 0; })
.append("text")
.attr("x", 8)
.attr("dy", ".35em")
.attr("transform", function(d) { return d.angle > Math.PI/2 && d.angle < Math.PI*3/2 ? "rotate(180) translate(-16)" : null; })
.style("text-anchor", function(d) { return d.angle > Math.PI/2 && d.angle < Math.PI*3/2? "end" : null; })
.text(function(d) {
return matrixKeys[d.index];
});
g.append("g")
.attr("class", "ribbons")
.selectAll("path")
.data(function(chords) {
return chords; })
.enter().append("path")
.attr("d", function(d) {
if(d.source.index%2 == 0) d.source.radius = innerRadius;
else d.source.radius = innerRadius + 50;
if(d.target.index%2 == 0) d.target.radius = innerRadius;
else d.target.radius = innerRadius + 50;
return ribbon(d);
})
.attr("class", function(d,i) { return matrixKeys[d.index]})
.style("fill", function(d) { return color(d.target.index); })
.style("stroke", function(d) { return d3.rgb(color(d.target.index)).darker(); });
// Returns an array of tick angles and values for a given group and step.
function groupTicks(d, step) {
var k = (d.endAngle - d.startAngle) / d.value;
return d3.range(0, d.value, step).map(function(value) {
return {
index:d.index,
value: value,
angle: value * k + d.startAngle
};
});
}
function fade(opacity, d2) {
var hightLight = g.selectAll(".ribbons path").filter(function(d) {
return d.source.index != d2.index && d.target.index != d2.index;
});
hightLight.transition()
.style("opacity", opacity);
}
</script>
<!DOCTYPE html>
<meta charset="utf-8">
<style>
body {
font: 20px sans-serif;
}
.group-tick line {
stroke: #000;
}
.ribbons {
fill-opacity: 0.67;
}
</style>
<svg width="800" height="800">
<defs>
<linearGradient id="Gradient1">
<stop class="stop1" offset="0%"/>
<stop class="stop2" offset="50%"/>
<stop class="stop3" offset="100%"/>
</linearGradient>
<linearGradient id="Gradient2" x1="0" x2="0" y1="0" y2="1">
<stop offset="0%" stop-color="red"/>
<stop offset="50%" stop-color="black" stop-opacity="0"/>
<stop offset="100%" stop-color="blue"/>
</linearGradient>
</defs>
</svg>
<script src="https://d3js.org/d3.v5.min.js"></script>
<script>
var matrixData={
"Occupants":
[0, 10,10,10,10,0,0,0,10,10,10,10,10],
"Flooring":
[70,0,0,0,0,0,30,0,0,0,0,0,0],
"Millwork":
[40, 0,0,0,0,0,60,0,0,0,0,0],
"Ceilings":
[60, 0,0,0,0,0,40,0,0,0,0,0,0],
"Wet Applied Products":
[60, 0,0,0,0,0,40,0,0,0,0,0,0],
"Curtain Wall":
[0, 0,0,0,0,0,100,0,0,0,0,0,0],
"Environment":
[0, 10,10,10,10,0,10,0,10,10,10,0,10],
"Roofing":
[0, 0,0,0,0,0,80,0,0,0,0,0],
"Insulation":
[50, 0,0,0,0,0,50,0,0,0,0,0,0],
"MEPFP":
[40, 0,0,0,0,0,60,0,0,0,0,0,0],
"Structure":
[50, 0,0,0,0,0,50,0,0,0,0,0,0],
"Furniture":
[90, 0,0,0,0,0,10,0,0,0,0,0,0]
}
matrix= Object.values(matrixData);
matrixKeys = Object.keys(matrixData);
var svg = d3.select("svg"),
width = +svg.attr("width"),
height = +svg.attr("height"),
outerRadius = Math.min(width, height) * 0.5 - 150,
innerRadius = outerRadius - 30;
var formatValue = d3.formatPrefix(",.0", 1e3);
var chord = d3.chord()
.padAngle(0.024)
.sortSubgroups(d3.descending);
var arc = d3.arc()
.innerRadius(innerRadius)
.outerRadius(outerRadius);
var ribbon = d3.ribbon();
var color = d3.scaleOrdinal()
.domain(d3.range(4))
.range(["#6FCDE3",
"#D7DAE5",
"#D7DAE5",
"#D7DAE5",
"#D7DAE5",
"#D7DAE5",
"#E5E52B",
"#D7DAE5",
"#D7DAE5",
"#D7DAE5",
"#D7DAE5",
"#D7DAE5"
]);
var g = svg.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ") rotate(75)")
.datum(chord(matrix));
var group = g.append("g")
.attr("class", "groups")
.selectAll("g")
.data(function(chords) { return chords.groups; })
.enter().append("g");
group.append("path")
.style("fill", function(d) { return color(d.index); })
.style("stroke", function(d) { return d3.rgb(color(d.index)).darker(); })
.attr("d", function(d,i) {
var radius = 0;
if(d.index%2 != 0) radius = 50;
return arc.innerRadius(innerRadius + radius)
.outerRadius(outerRadius + radius)(d);}).on("mouseover", function(d,i) {
fade(.1,d);
})
.on("mouseout", function(d,i) {
fade(1,d);
});
var groupTick = group.selectAll(".group-tick")
.data(function(d) { return groupTicks(d, 1e3); })
.enter().append("g")
.attr("class", "group-tick")
.attr("transform", function(d) {
var radius = 0;
if(d.index%2 != 0) radius = 50;
return "rotate(" + (d.angle * 180 / Math.PI - 75) +
") translate(" + (outerRadius + radius) + ",2)";
});
groupTick.append("line")
.attr("x2", 6);
groupTick
.filter(function(d) { return d.value % 5e3 === 0; })
.append("text")
.attr("x", 8)
.attr("dy", ".35em")
.attr("transform", function(d) { return d.angle > Math.PI/2 && d.angle < Math.PI*3/2 ? "rotate(180) translate(-16)" : null; })
.style("text-anchor", function(d) { return d.angle > Math.PI/2 && d.angle < Math.PI*3/2? "end" : null; })
.text(function(d) {
return matrixKeys[d.index];
});
g.append("g")
.attr("class", "ribbons")
.selectAll("path")
.data(function(chords) {
return chords; })
.enter().append("path")
.attr("d", function(d) {
if(d.source.index%2 == 0) d.source.radius = innerRadius;
else d.source.radius = innerRadius + 50;
if(d.target.index%2 == 0) d.target.radius = innerRadius;
else d.target.radius = innerRadius + 50;
return ribbon(d);
})
.attr("class", function(d,i) { return matrixKeys[d.index]})
.style("fill", function(d) { return color(d.target.index); })
.style("stroke", function(d) { return d3.rgb(color(d.target.index)).darker(); });
// Returns an array of tick angles and values for a given group and step.
function groupTicks(d, step) {
var k = (d.endAngle - d.startAngle) / d.value;
return d3.range(0, d.value, step).map(function(value) {
return {
index:d.index,
value: value,
angle: value * k + d.startAngle
};
});
}
function fade(opacity, d2) {
var hightLight = g.selectAll(".ribbons path").filter(function(d) {
return d.source.index != d2.index && d.target.index != d2.index;
});
hightLight.transition()
.style("opacity", opacity);
}
</script>
answered Nov 17 at 2:40
Umesh Maharshi
1,040410
1,040410
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53247071%2fd3-js-chord-diagram-make-chords-touch-the-pulled-apart-arc%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
with exact the same method as you pulled the arc apart
– rioV8
Nov 11 at 9:54