Built with blockbuilder.org
forked from ojassvi's block: cluster draft 3
license: mit |
Built with blockbuilder.org
forked from ojassvi's block: cluster draft 3
{ | |
"clusters": [ | |
{ | |
"id": "1", | |
"cluster": "a", | |
"asset": "ojassvi" | |
}, | |
{ | |
"id": "2", | |
"cluster": "a", | |
"asset": "mohan" | |
}, | |
{ | |
"id": "3", | |
"cluster": "b", | |
"asset": "linli" | |
}, | |
{ | |
"id": "4", | |
"cluster": "a", | |
"asset": "trupti" | |
}, | |
{ | |
"id": "5", | |
"cluster": "b", | |
"asset": "niranjan" | |
}, | |
{ | |
"id": "6", | |
"cluster": "c", | |
"asset": "rohan" | |
}, | |
{ | |
"id": "7", | |
"cluster": "a", | |
"asset": "jeff" | |
}, | |
{ | |
"id": "8", | |
"cluster": "b", | |
"asset": "hazim" | |
}, | |
{ | |
"id": "9", | |
"cluster": "c", | |
"asset": "m4" | |
}, | |
{ | |
"id": "10", | |
"cluster": "c", | |
"asset": "rick" | |
}, | |
{ | |
"id": "11", | |
"cluster": "c", | |
"asset": "m1" | |
}, | |
{ | |
"id": "12", | |
"cluster": "c", | |
"asset": "m2" | |
}, | |
{ | |
"id": "13", | |
"cluster": "c", | |
"asset": "m3" | |
}, | |
{ | |
"id": "14", | |
"cluster": "c", | |
"asset": "m4" | |
} | |
] | |
} |
<!DOCTYPE html> | |
<meta charset="utf-8"> | |
<style> | |
svg {border: 1px solid} | |
</style> | |
<svg width="500" height="400"></svg> | |
<script src="https://d3js.org/d3.v4.min.js"></script> | |
<script> | |
const input = { | |
"clusters": [ | |
{ | |
"id": "1", | |
"cluster": "a", | |
"asset": "ojassvi" | |
}, | |
{ | |
"id": "2", | |
"cluster": "a", | |
"asset": "mohan" | |
}, | |
{ | |
"id": "3", | |
"cluster": "b", | |
"asset": "linli" | |
}, | |
{ | |
"id": "4", | |
"cluster": "a", | |
"asset": "trupti" | |
}, | |
{ | |
"id": "5", | |
"cluster": "b", | |
"asset": "niranjan" | |
}, | |
{ | |
"id": "6", | |
"cluster": "c", | |
"asset": "rohan" | |
}, | |
{ | |
"id": "7", | |
"cluster": "a", | |
"asset": "jeff" | |
}, | |
{ | |
"id": "8", | |
"cluster": "b", | |
"asset": "hazim" | |
}, | |
{ | |
"id": "9", | |
"cluster": "c", | |
"asset": "m4" | |
}, | |
{ | |
"id": "10", | |
"cluster": "c", | |
"asset": "rick" | |
}, | |
{ | |
"id": "11", | |
"cluster": "c", | |
"asset": "m1" | |
}, | |
{ | |
"id": "12", | |
"cluster": "c", | |
"asset": "m2" | |
}, | |
{ | |
"id": "13", | |
"cluster": "c", | |
"asset": "m3" | |
}, | |
{ | |
"id": "14", | |
"cluster": "c", | |
"asset": "m4" | |
}, | |
{ | |
"id": "15", | |
"cluster": "a", | |
"asset": "a1" | |
}, | |
{ | |
"id": "16", | |
"cluster": "b", | |
"asset": "b1" | |
}, | |
{ | |
"id": "17", | |
"cluster": "a", | |
"asset": "a3" | |
}, | |
{ | |
"id": "18", | |
"cluster": "b", | |
"asset": "a4" | |
}, | |
{ | |
"id": "19", | |
"cluster": "a", | |
"asset": "a5" | |
}, | |
{ | |
"id": "20", | |
"cluster": "b", | |
"asset": "a6" | |
}, | |
{ | |
"id": "21", | |
"cluster": "c", | |
"asset": "m11" | |
}, | |
{ | |
"id": "22", | |
"cluster": "c", | |
"asset": "m21" | |
}, | |
{ | |
"id": "23", | |
"cluster": "c", | |
"asset": "m31" | |
}, | |
{ | |
"id": "24", | |
"cluster": "c", | |
"asset": "m41" | |
}, | |
{ | |
"id": "25", | |
"cluster": "a", | |
"asset": "a11" | |
}, | |
{ | |
"id": "26", | |
"cluster": "b", | |
"asset": "b11" | |
}, | |
{ | |
"id": "27", | |
"cluster": "a", | |
"asset": "a32" | |
}, | |
{ | |
"id": "28", | |
"cluster": "b", | |
"asset": "a41" | |
}, | |
{ | |
"id": "29", | |
"cluster": "a", | |
"asset": "trupti1" | |
}, | |
{ | |
"id": "30", | |
"cluster": "b", | |
"asset": "niranjan1" | |
}, | |
] | |
} | |
function prepareData(input) { | |
const clusters = {}; | |
input.forEach(item => { | |
const cl = item.cluster | |
if(!clusters[cl]) { | |
clusters[cl] = {nodes: [], id: cl}; | |
} | |
clusters[cl].nodes.push(item); | |
}); | |
return Object.keys(clusters).map(key => clusters[key]); | |
} | |
const smallRadius = 5; | |
var svg = d3.select("svg"); | |
var g = svg.append("g"); | |
const innerPadding = 1; | |
function buildInnerCircles(data) { | |
const nodes = data.nodes; | |
var simulation = d3.forceSimulation(nodes) | |
.force("x", d3.forceX(data.x)) | |
.force("y", d3.forceY(data.y)) | |
.force("collide", d3.forceCollide(smallRadius + innerPadding)) | |
.stop(); | |
for (var i = 0; i < 100; ++i) simulation.tick(); | |
svg.select(`#${data.id}`) | |
.selectAll("g") | |
.data(nodes) | |
.enter() | |
.append("circle") | |
.attr("r", smallRadius) | |
.attr("cx", function(d) { return d.x; }) | |
.attr("cy", function(d) { return d.y; }) | |
.attr("fill", "#03c5ed"); | |
} | |
function buildOuterCircles(data) { | |
var svg = d3.select("svg"), | |
width = svg.attr("width"), | |
height = svg.attr("height"); | |
var g = svg.append("g"); | |
const outerPadding = 1; | |
var simulation = d3.forceSimulation(data) | |
.force("x", d3.forceX(width / 2 )) | |
.force("y", d3.forceY(height / 2)) | |
.force("collide", d3.forceCollide( | |
function(d){return getOuterRadius(d.nodes) + outerPadding})) | |
.stop(); | |
for (var i = 0; i < 100; ++i) simulation.tick(); | |
var cell = g.selectAll("g") | |
.data(data) | |
.enter() | |
.append("g") | |
.attr("id", d => d.id) | |
.append("circle") | |
.attr("r", d => getOuterRadius(d.nodes)) | |
.attr("cx", d => d.x ) | |
.attr("cy", d => d.y ) | |
.attr("fill", "none") | |
.attr("stroke", "gray") | |
.each(buildInnerCircles); | |
// buildInnerCircles(data); | |
} | |
function type(d) { | |
if (!d.value) return; | |
d.value = +d.value; | |
return d; | |
} | |
function getOuterRadius(nodes) { | |
return (nodes.length - 3) * smallRadius; | |
} | |
const output = prepareData(input.clusters); | |
buildOuterCircles(output) | |
</script> |