Current look:

What I'm after:

Visual Issue:
I have been trying to create a doughnut chart with clustered bubbles. The goal is to have all the bubbles grouped closely together in the center of the doughnut chart. However, the current implementation does not produce the expected result.
What I've Tried:
I have attempted to cluster the bubbles by calculating their positions relative to the center of the chart. I've used polar coordinates to determine their locations, but the bubbles still do not cluster as desired.
Desired Outcome:
I want all the bubbles to be tightly clustered together at the center of the doughnut chart, creating a visually appealing and coherent representation of the data.
Request for Assistance:
I'm seeking guidance on how to modify my code to achieve the desired clustering effect. Are there any adjustments or approaches that I should consider to make the bubbles cluster together effectively in the center of the doughnut chart?
class BubbleChart {
constructor(canvasId, data) {
this.canvasId = canvasId;
this.data = data;
this.initVis();
}
initVis() {
let vis = this; // Define 'vis' as a reference to the class instance
// Initialize chart dimensions and other settings using 'vis'
vis.margin = { top: 100, right: 50, bottom: 50, left: 110 };
vis.width = 400 - vis.margin.left - vis.margin.right; // Width of the bubble chart canvas
vis.height = 400 - vis.margin.top - vis.margin.bottom; // Height of the bubble chart canvas
vis.createChart();
}
createChart() {
let vis = this; // Reference to the class instance
const canvas = document.getElementById(vis.canvasId);
const ctx = canvas.getContext('2d');
// Define the number of bubbles
const numBubbles = vis.data.length;
const clusterRadius = Math.min(vis.width, vis.height) * 0.3; // Radius of the cluster
// Calculate the positions of bubbles closely together in the center
const clusterX = vis.width / 2; // Cluster center X
const clusterY = vis.height / 2; // Cluster center Y
const angleIncrement = (2 * Math.PI) / numBubbles; // Angle increment for placing bubbles
const bubbleData = {
datasets: [{
label: vis.data.map(d => d.Topic),
backgroundColor: vis.data.map((_, i) => vis.getColor(i)),
data: vis.data.map((item, i) => {
// Calculate positions closely together in the center
const bubbleAngle = i * angleIncrement; // Angle for the current bubble within the cluster
const bubbleX = clusterX + clusterRadius * Math.cos(bubbleAngle); // Adjusted X within cluster
const bubbleY = clusterY + clusterRadius * Math.sin(bubbleAngle); // Adjusted Y within cluster
const r = 10; // Use a fixed radius for all bubbles within the cluster
return {
x: bubbleX,
y: bubbleY,
r: r
};
})
}]
};
new Chart(ctx, {
type: 'bubble',
data: bubbleData,
options: {
plugins: {
legend: {
display: false // This will hide the legend
}
},
scales: {
x: { display: false },
y: { display: false }
},
tooltips: { // Ensure tooltips are enabled for hover information
enabled: true
},
maintainAspectRatio: false
}
});
}
getColor(index) {
const colors = ['#FF6384', '#36A2EB', '#FFCE56', '#4BC0C0', '#9966FF', '#FF9F40'];
return colors[index % colors.length];
}
}