Skip to content

Instantly share code, notes, and snippets.

@GitNoise
Last active May 17, 2019 07:30
Show Gist options
  • Save GitNoise/cbcc279b53c78d254523bba3dc845b59 to your computer and use it in GitHub Desktop.
Save GitNoise/cbcc279b53c78d254523bba3dc845b59 to your computer and use it in GitHub Desktop.
donut chart w. d3-annotations
license: mit
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3-annotation/2.3.2/d3-annotation.min.js"></script>
<style>
body { margin:0;position:fixed;top:0;right:0;bottom:0;left:0; }
.label {
position: absolute;
text-align: center;
font-family: Arial;
font-size: 12px;
color: #222222;
}
.label > span {
font-size: 28px;
font-weight: bold;
font-family: TimesNewRomanPS-BoldMT;
}
.connector {
fill: red;
}
.annotation-group path {
fill: white;
stroke: #222222;
}
.annotation-note-label, .annotation-note-title {
fill: #222222;
}
.annotation-note-bg {
stroke: black;
}
</style>
</head>
<body>
<script>
var width = 475,
height = 220,
annotationWrap = 120,
innerRadius = 80,
outerRadius = 100,
radius = outerRadius + 25;
var data = [
{ value: 10, label: "EJ PÅBÖRJADE", color: "#f0f0f0", sufix:'%' },
{ value: 2, label: 'GENOMFÖRDA', color: "#6f808c", sufix:'%' },
{ value: 2, label: 'GENOMFÖRDA', color: "#6f808c", sufix:'%' },
{ value: 2, label: 'GENOMFÖRDA', color: "#6f808c", sufix:'%' },
{ value: 2, label: 'GENOMFÖRDA', color: "#6f808c", sufix:'%' },
{ value: 66, label: 'EJ GENOMFÖRDA', color: "#f18163", sufix:'%' },
];
var annotations = [];
var pie = d3.pie()
.value(function(d) { return d.value; })
.sort(null);
var arc = d3.arc()
.innerRadius(innerRadius)
.outerRadius(outerRadius)
.startAngle(d => d.startAngle)
.endAngle(d => d.endAngle);
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
var slice = svg.append("g")
.attr("transform", "translate(" + width/2 + "," + height / 2 + ")")
.attr("class", "field")
.selectAll(".slice")
.data(pie(data))
.enter()
.append("g")
.classed("slice", true)
slice
.append("path")
.attr("class", "slice path path--background")
.attr("d", arc )
.style("fill", d => d.data.color || '#a0a0a0');
slice.each(function(d,e) {
const pieArcCentroid = arc.centroid(d);
annotations.push({
note: {
label: d.data.label,
title: `${d.data.value}${ d.data.sufix ? ' ' + d.data.sufix: '' }`,
wrap: annotationWrap,
align: Math.sign(pieArcCentroid[0]) > 0 ? "left" : "right"
},
connector: {
end: "dot",
},
xStart: width/2 + pieArcCentroid[0],
yStart: height/2 + pieArcCentroid[1],
nx: Math.sign(pieArcCentroid[0]) > 0 ? width - annotationWrap : annotationWrap,
nxStart: Math.sign(pieArcCentroid[0]) > 0 ? width - annotationWrap : annotationWrap,
ny: height/2 + pieArcCentroid[1],
isRightSide: Math.sign(pieArcCentroid[0]) > 0,
isLeftSide: Math.sign(pieArcCentroid[0]) > 0,
});
});
const rightAnnotations = annotations.filter(d => d.isRightSide);
const leftAnnotations = annotations.filter(d => d.isLeftSide);
const dotradius = 20;
svg.append("g").classed("pre", true).selectAll("circle")
.data(rightAnnotations)
.enter()
.append("circle")
.attr("cx", d => d.nx)
.attr("cy", d => d.ny)
.attr("r", dotradius)
.style("stroke", "black")
.style("stroke-opacity",0.5)
.style("fill-opacity",0)
const force = d3.forceSimulation()
.nodes(rightAnnotations)
.force('manybodies', d3.forceManyBody().strength(1))
.force('collide', d3.forceCollide(dotradius))
.force('axis', d3.forceX(d => d.x).strength(1))
.force('axis', box_force)
.stop();
function box_force() {
for (var i = 0, n = rightAnnotations.length; i < n; ++i) {
let curr_node = rightAnnotations[i];
curr_node.x = curr_node.nxStart;
curr_node.y = Math.max(dotradius+10, Math.min(height - radius, curr_node.y));
}
}
for(let i=0; i<100; i++) force.tick();
console.table(rightAnnotations)
svg.append("g").classed("post", true).selectAll("circle")
.data(rightAnnotations)
.enter()
.append("circle")
.attr("cx", d => d.x)
.attr("cy", d => d.y)
.attr("r", dotradius)
.style("fill", "red")
.style("fill-opacity", 0.2)
/*
const makeAnnotations = d3.annotation()
.type(d3.annotationCalloutCircle)
.annotations(rightAnnotations)
d3.select("svg")
.append("g")
.attr("class", "annotation-group")
.call(makeAnnotations);
*/
</script>
</body>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment