<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
<title>Chord Diagram</title>
<script src="https://d3js.org/d3.v5.min.js"></script>
<link
href="https://fonts.googleapis.com/css?family=Lato:400,900"
rel="stylesheet"
type="text/css"
/>
<link
rel="stylesheet"
href="https://unpkg.com/tippy.js@6/themes/translucent.css"
/>
<style>
.tippy-content {
font-family: "Lato", sans-serif;
}
#chart-540c5e93 {
font-size: 16px;
font-family: "Lato", sans-serif;
text-align: center;
fill: #454545;
}
#chart-540c5e93 svg {
max-width: 700.0px;
}
.details_thumbs {
margin:5.0px;
max-width:85.0px;
padding:0;
display:inline-block;
}
.details_thumbs img {
max-width:85.0px;
}
.details_thumbs figcaption {
text-align: center;
font-size: 14.0px;
}
.hidden_chord{
display:none;
}
@media (min-width: 600px) {
#chart-540c5e93{
font-size: 20px;
}
}
</style>
</head>
<body>
<div id="chart-540c5e93" class="chord">
</div>
<script src="https://unpkg.com/@popperjs/core@2"></script>
<script src="https://unpkg.com/tippy.js@6"></script>
<script>
var script = document.createElement("script");
script.type = "text/javascript";
script.src = "https://d3js.org/d3.v5.min.js";
script.onload = function () {
var script2 = document.createElement("script");
script2.type = "text/javascript";
script2.src = "https://shahinrostami.com/assets/chord/script.js";
script2.onload = function () {
margin = {
left: 0.0,
top: 0.0,
right: 0.0,
bottom: 0.0
};
width = Math.min(window.innerWidth, 700.0) - margin.left - margin.right;
height = Math.min(window.innerWidth, 700.0) - margin.top - margin.bottom;
innerRadius = Math.min(width, height) * 0.39;
outerRadius = innerRadius * 1.1;
tag_id = "chart-540c5e93";
padding = 0;
Names = ['A', 'B', 'C', 'divide', '1', '2', '3', 'divide'];
colors = ['#7400B8', '#5E60CE', '#5684D6', '#000000', '#56CFE1', '#64DFDF', '#80FFDB', '#000000'];
opacityDefault = 0.8;
matrix = [[0.0, 0.0, 0.0, 0.0, 1.0, 4.0, 1.0, 0.0], [0.0, 0.0, 0.0, 0.0, 1.0, 3.0, 2.0, 0.0], [0.0, 0.0, 0.0, 0.0, 1.0, 2.0, 2.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0], [4.0, 3.0, 2.0, 0.0, 0.0, 0.0, 0.0, 0.0], [1.0, 2.0, 2.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]];
wrap_labels = false;
credit = true;
details = [];
details_thumbs = [];
noun = "instances";
details_separator = ", ";
divide = true;
divide_idx = 3;
divide_size = 0.5;
instances = 17.0;
popup_width = 350.0;
if(divide){
emptyStroke = Math.round(instances * divide_size);
matrix[divide_idx][Names.length-1] = emptyStroke
matrix[Names.length-1][divide_idx] = emptyStroke
var offset = (2 * Math.PI * (emptyStroke / (instances + emptyStroke))) / 4;
}
else{
offset = 0;
}
var colors = d3
.scaleOrdinal()
.domain(d3.range(Names.length))
.range(colors);
var chord = customChordLayout()
.padding(padding)
.sortChords(d3.descending) .matrix(matrix);
var arc = d3
.arc()
.innerRadius(innerRadius * 1.01)
.outerRadius(outerRadius)
.startAngle(startAngle)
.endAngle(endAngle);
var path = d3.ribbon()
.radius(innerRadius)
.startAngle(startAngle)
.endAngle(endAngle);
var svg = d3
.select("#" + tag_id)
.append("svg")
.attr(
"viewBox",
"0 0 " +
(width + margin.left + margin.right) +
" " +
(height + margin.top + margin.bottom)
)
.attr("preserveAspectRatio", "xMinYMin meet")
.append("g")
.attr(
"transform",
"translate(" +
(width / 2 + margin.left) +
"," +
(height / 2 + margin.top) +
")"
);
d3.select("#" + tag_id)
.append("span")
.style("display", "block")
.style("font-size", "12px")
.style("text-align", "right")
.style("font-family", '"Arial", sans-serif')
.html(
'made with <a href="https://github.com/shahinrostami/chord">chord</a> [<a href="https://twitter.com/shahinrostami">@ShahinRostami</a>]'
);
if(credit){
d3.select("#" + tag_id).select("span")
.append("span")
.style("font-size", "12px")
.style("font-family", '"Arial", sans-serif')
.html(
'<br>see more at <a href="https://stamilabs.com">StamiLabs.com</a>'
);
}
function getGradID(d) {
return (
"linkGrad-" + tag_id + "-" + d.source.index + "-" + d.target.index
);
}
var grads = svg
.append("defs")
.selectAll("linearGradient")
.data(chord.chords())
.enter()
.append("linearGradient")
.attr("id", getGradID)
.attr("gradientUnits", "userSpaceOnUse")
.attr("x1", function (d, i) {
return (
innerRadius *
Math.cos(
(d.source.endAngle - d.source.startAngle) / 2 +
d.source.startAngle -
Math.PI / 2
)
);
})
.attr("y1", function (d, i) {
return (
innerRadius *
Math.sin(
(d.source.endAngle - d.source.startAngle) / 2 +
d.source.startAngle -
Math.PI / 2
)
);
})
.attr("x2", function (d, i) {
return (
innerRadius *
Math.cos(
(d.target.endAngle - d.target.startAngle) / 2 +
d.target.startAngle -
Math.PI / 2
)
);
})
.attr("y2", function (d, i) {
return (
innerRadius *
Math.sin(
(d.target.endAngle - d.target.startAngle) / 2 +
d.target.startAngle -
Math.PI / 2
)
);
});
grads
.append("stop")
.attr("offset", "0%")
.attr("stop-color", function (d) {
return colors(d.source.index);
});
grads
.append("stop")
.attr("offset", "100%")
.attr("stop-color", function (d) {
return colors(d.target.index);
});
var outerArcs = svg
.selectAll("g.group")
.data(chord.groups)
.enter()
.append("g")
.attr("class", "group")
.on("mouseover", fade(0.1, 1))
.on("mouseout", fade(opacityDefault, opacityDefault));
outerArcs
.append("path")
.style("fill", function (d) {
return colors(d.index);
})
.attr("d", arc)
.attr("class", function (d) {
if(divide){
if(d.index == divide_idx || d.index == matrix.length -1){
return "hidden_chord";
}
}
})
.each(function (d, i) {
var firstArcSection = /(^.+?)L/;
var newArc = firstArcSection.exec(d3.select(this).attr("d"))[1];
newArc = newArc.replace(/,/g, " ");
if (
(d.endAngle > (90 * Math.PI) / 180) &
(d.startAngle < (270 * Math.PI) / 180)
) {
var startLoc = /M(.*?)A/, middleLoc = /A(.*?)0 0 1/, endLoc = /0 0 1 (.*?)$/; var newStart = endLoc.exec(newArc)[1];
var newEnd = startLoc.exec(newArc)[1];
var middleSec = middleLoc.exec(newArc)[1];
newArc = "M" + newStart + "A" + middleSec + "0 0 0 " + newEnd;
}
svg
.append("path")
.attr("class", "hiddenArcs")
.attr("id", "arc-" + tag_id + "-" + i)
.attr("d", newArc)
.style("fill", "none");
});
if (wrap_labels) {
outerArcs
.append("text")
.attr("class", "titles")
.attr("dy", function (d, i) {
return (d.endAngle > (90 * Math.PI) / 180) &
(d.startAngle < (270 * Math.PI) / 180)
? 25
: -16;
})
.append("textPath")
.attr("startOffset", "50%")
.style("text-anchor", "middle")
.attr("xlink:href", function (d, i) {
return "#arc-" + tag_id + "-" + i;
})
.text(function (d, i) {
return Names[i];
});
} else {
outerArcs
.append("text")
.each(function (d) {
d.angle = (d.startAngle + d.endAngle) / 2 + offset;
})
.attr("dy", ".35em")
.attr("class", function (d) {
if(divide){
if(d.index == divide_idx || d.index == matrix.length -1){
return "titles hidden_chord";
}
else{
return "chord";
}
}
else{
return "titles";
}
})
.attr("text-anchor", function (d) {
return d.angle > Math.PI ? "end" : null;
})
.attr("transform", function (d) {
return (
"rotate(" +
((d.angle * 180) / Math.PI - 90) +
")" +
"translate(" +
(outerRadius + 10) +
")" +
(d.angle > Math.PI ? "rotate(180)" : "")
);
})
.text(function (d, i) {
return Names[i];
});
}
svg
.selectAll("path.chord")
.data(chord.chords)
.enter()
.append("path")
.attr("class", function (d) {
if(divide){
if(d.source.index == divide_idx){
return "chord hidden_chord";
}
else{
return "chord";
}
}
else{
return "chord";
}
})
.style("fill", function (d) {
return "url(#" + getGradID(d) + ")";
})
.style("opacity", opacityDefault)
.attr("d", path)
.on("mouseover", mouseoverChord(noun, details, details_thumbs, details_separator, popup_width))
.on("mouseout", mouseoutChord(opacityDefault, opacityDefault));
function startAngle(d) {
return d.startAngle + offset;
}
function endAngle(d) {
return d.endAngle + offset;
}
function fade(opacityIn, opacityOut) {
return function (d, i) {
d3.select(this.ownerSVGElement)
.selectAll("path.chord")
.filter(function (d) {
return d.source.index !== i && d.target.index !== i;
})
.transition()
.style("opacity", opacityIn);
d3.select(this.ownerSVGElement)
.selectAll("path.chord")
.filter(function (d) {
return d.source.index == i || d.target.index == i;
})
.transition()
.style("opacity", opacityOut);
};
}
function mouseoverChord(noun, details, details_thumbs, details_separator, popup_width) {
return function (d, i) {
d3.select(this.ownerSVGElement)
.selectAll("path.chord")
.transition()
.style("opacity", 0.1);
d3.select(this).transition().style("opacity", 1);
tippy_content = "<span style='font-weight:900'>" +
Names[d.source.index] +
"</span> and <span style='font-weight:900'>" +
Names[d.target.index] +
"</span><br>occur together in <span style='font-weight:900'>" +
d.source.value +
"</span> " + noun;
if (Array.isArray(details) && details.length &&
Array.isArray(details_thumbs) && details_thumbs.length) {
if (Array.isArray(details[d.source.index][d.target.index]) && details[d.source.index][d.target.index].length &&
Array.isArray(details_thumbs[d.source.index][d.target.index]) && details_thumbs[d.source.index][d.target.index].length) {
var figures = '';
for(var i = 0; i < details[d.source.index][d.target.index].length; i++) {
figures += "<figure class='details_thumbs'><img src=" + details_thumbs[d.source.index][d.target.index][i] + "><figcaption>" + details[d.source.index][d.target.index][i] + "</figcaption></figure>"
}
tippy_content = tippy_content +
"<br><br><center><span><em>" +
figures +
"</em></span></center>";
}
}
else if (Array.isArray(details) && details.length) {
if (Array.isArray(details[d.source.index][d.target.index]) && details[d.source.index][d.target.index].length) {
tippy_content = tippy_content +
"<br><br><span><em>" +
details[d.source.index][d.target.index].join(details_separator) +
"</em></span>";
}
}
else if (Array.isArray(details_thumbs) && details_thumbs.length) {
if (Array.isArray(details_thumbs[d.source.index][d.target.index]) && details_thumbs[d.source.index][d.target.index].length) {
var figures = '';
for(var i = 0; i < details_thumbs[d.source.index][d.target.index].length; i++) {
figures += "<figure class='details_thumbs'><img src=" + details_thumbs[d.source.index][d.target.index][i] + "></figure>"
}
tippy_content = tippy_content +
"<br><br><center><span><em>" +
figures +
"</em></span></center>";
}
}
if(this._tippy == null)
{
tippy(this, {
allowHTML: true,
followCursor: true,
content: tippy_content,
size: "large",
arrow: true,
maxWidth: popup_width,
theme:'translucent',
});
}
};
}
function mouseoutChord(opacityIn, opacityOut) {
return function (d, i) {
d3.select(this.ownerSVGElement)
.selectAll("path.chord")
.transition()
.style("opacity", opacityOut);
};
}
};
document.body.appendChild(script2);
};
document.body.appendChild(script);
</script>
<script></script>
</body>
</html>