PackedCircle
Feature Proposal
I have a need for a PackedCircle chart - similar to a TreeMap but arbitrary sized circles clustered around a center (my use case only requires a single level rather than nested)
have found them supported in a number of other libraries, and while they are not as space efficient as treemaps, it's something I keep getting requests to support in the internal dashboard I maintain
Possible Implementation
had started a discussion on https://github.com/kurkle/chartjs-chart-treemap/issues/15 and as well as the packing solution they use found this https://stackoverflow.com/a/21612877/1569675 (not DS3 specific, just a canvas implementation). As an interim, I might experiment with using this logic and then using it to populate a bubble chart, though it doesn't assign a 'center of gravity' to the middle of the box which would be a more desirable behavior
With some carefull own logic with creating the bubbles you could create this already using a bubble chart. But if you want it as an chart type that does that logic for you I think it would suit better as an external chart type and not something for the core
With some carefull own logic with creating the bubbles you could create this already using a bubble chart. But if you want it as an chart type that does that logic for you I think it would suit better as an external chart type and not something for the core
agreed, it's probably not core. I've got close using the sample I linked, but getting the returned X,Y, and Radius scaled to fit into the canvas is making my head hurt! Sample code here in case it's of use to anyone (and hopefully someone points to where I'm going wrong) - at the moment there's still sometimes gaps or overlay of the circles that I don't see in the jsfiddle, and bubbles get clipped at the edge of the canvas.
<canvas id="canvas" style="width:450px; height:450px;"></canvas>
// include the calculation code from https://jsfiddle.net/TDzVE/
var radiuses = [];
for(var i=0; i<15; i++) {
radiuses.push(Math.random() * (200) + 1)
}
var packer = new Packer (radiuses, 1);
var chart = $("#canvas")
var margin_factor = 0.1;
var mx = chart.width() * margin_factor / 2;
var my = chart.height() * margin_factor / 2;
dx=Number(packer.w)/2
dy=Number(packer.h)/2
var zx = chart.width() / packer.w;
var zy = chart.height() / packer.h;
var zoom = zx < zy ? zx : zy;
datapoints = [];
for (var i=0; i<packer.list.length;i++) {
circle = packer.list[i]
datapoints.push({'x':(circle.c.x+dx)*zoom+mx, 'y':(circle.c.y+dy)*zoom+my, 'r':circle.r*zoom})
}
const data = {
datasets: [
{
label: 'Dataset 1',
data: datapoints,
backgroundColor: "rgba(123,123,123,1)",
},
]
};
var myBarChart = new Chart(chart, {
type: 'bubble',
data: data,
options: {
responsive : false,
maintainAspectRatio : true,
layout : {
autoPadding : false,
},
scales: {
x: {
ticks: {display: false,},
grid: { display: false },
border: {display: false}
},
y: {display:false,
ticks: {display: false,},
grid: { display: false, },
border: {display: false}
}
},
plugins: {
legend: {display: false,},
title: {display: false,}
}
},
})
another, clunky, solution using the D3 v3 layout.pack algorithm https://stackoverflow.com/a/76911169/1569675
Would love this as well