Built with blockbuilder.org
xxxxxxxxxx
<head>
<meta charset="utf-8">
<script src="https://d3js.org/d3.v4.min.js"></script>
<style>
body { margin:0;position:fixed;top:0;right:0;bottom:0;left:0;
}
svg {
border: 1px solid black;
margin: 20px;
}
.overlap {
fill: orange;
fill-opacity: 0.2;
stroke: orange;
}
.alone {
fill: steelblue;
fill-opacity: 0.2;
stroke: steelblue;
}
line {
stroke-width: 1px;
stroke: black;
stroke-opacity: 0.7
}
.dot {
fill: none;
stroke: black;
}
</style>
</head>
<body>
<script>
const width = 500;
const height = 500;
const radius = 20;
const joinRadius = 20;
const svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height)
for(let i=0; i<4; i++) {
svg.append("circle")
.classed("overlap", true)
.attr("id", "c_" + i)
.attr("cy", height/2)
.attr("cx", width/2)
.attr("r", radius)
}
svg.append("circle")
.classed("alone", true)
.attr("cy", height/2 + 10)
.attr("cx", width/2 + 10)
.attr("r", radius)
const bins = [];
svg.selectAll("circle").each(
(xxx, i, d) => {
const elem = d3.select(d[i]);
const x = elem.attr("cx");
const y = elem.attr("cy");
const indexOf = bins.findIndex(b => b.id === x + "" + y);
if (indexOf === -1) {
bins.push({
id: x + "" + y,
items: [elem]
});
}
else {
bins[indexOf].items.push(elem);
}
});
bins.forEach(bin => {
if(bin.items.length > 1) {
const cx = parseInt(bin.items[0].attr("cx"));
const cy = parseInt(bin.items[0].attr("cy"));
bin.items.forEach((circle, i) => {
circle.attr("transform", `translate(${50 + i*radius*2 + i*4}, -50)`);
})
svg.append("line")
.attr("x1", cx)
.attr("y1", cy)
.attr("x2", cx + 50 - radius)
.attr("y2", cy - 50 + radius + 4);
svg.append("line")
.attr("x1", cx + 50 - radius)
.attr("y1", cy - 50 + radius + 4)
.attr("x2", cx + 50 + bin.items.length * radius * 2)
.attr("y2", cy - 50 + radius + 4);
}
});
</script>
</body>
https://d3js.org/d3.v4.min.js