Built with blockbuilder.org
forked from GitNoise's block: donut chart
license: mit |
Built with blockbuilder.org
forked from GitNoise's block: donut chart
<!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> |