'Need to create packed bubble chart using html canvas

I am new to canvas, needs to create packed bubble chart using html canvas. Please note we didn't want to go for any other thirdparty bubble charts library. I created canvas rectangle with bubbles already, but all the bubbles placed in row manner not packed bubble charts.

I have attached the code,

    <!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<body>
<canvas id="canvas" width="700" height="500" style="border:1px solid #d3d3d3;">Your browser does not support the HTML5 canvas tag.</canvas>

</div>

<style>
.blinkingClass {<!--from  ww w .  j  ava2  s .  co m-->
  outline: red;
  color: red;
  background-color: red;
  -webkit-animation: blink .75s linear infinite;
  -moz-animation: blink .75s linear infinite;
  -ms-animation: blink .75s linear infinite;
  -o-animation: blink .75s linear infinite;
  animation: blink .75s linear infinite;
}
</style>
<script>
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
ctx.imageSmoothingEnabled = true;

var canvasOffset = $("#canvas").offset();
var offsetX = canvasOffset.left;
var offsetY = canvasOffset.top;

var canvasWidth = 1200;

var d1 = new Map();
d1.set('d1c++', 4);
d1.set('d1tcl', 12);
d1.set('d1groovy', 70);
d1.set('jj', 3);
d1.set('kk', 10);
d1.set('ll', 60);
d1.set('mm', 30);
d1.set('nn', 20);
d1.set('oo', 60);
d1.set('pp', 3);
d1.set('qq', 10);
d1.set('rr', 60);
d1.set('ss', 20);
d1.set('tt', 40);
d1.set('uu', 10);
d1.set('vv', 2);
d1.set('ww', 23);










var dataMap = new Map();

dataMap.set("d1", d1);




var fps = 10;
var percent = 0
var direction = 1;
var renderSize = {width:50, height:50};
    



var controlPt = 0;


var dots = [];

function animate() {
    percent += direction;
    if (percent < 0) {
        percent = 0;
        direction = 1;
    };
    if (percent >= 100) {
        percent = 0;
        direction = 1;
    };

    draw(percent);

    setTimeout(function () {
        requestAnimationFrame(animate);
    }, 1000 / fps);
}


// draw the current frame based on sliderValue
function draw(sliderValue) {
    var xy;
    ctx.beginPath();

    ctx.clearRect(0, 0, canvas.width, canvas.height);
    
    
    
    
    ctx.lineWidth = 1;
    
    
    
    var dataCenterBoxPosX = 40;
    var dataCenterBoxPosY = 40;

    var rectWidth = 400
    var rectHeight = 400
    
    var dataCenterPosMap = new Map();
    
    var appPosMap = new Map();
    var pos = 400;
    Array.from(dataMap.keys()).map(datacenter => {
        var map = dataMap.get(datacenter);
        ctx.beginPath();
        
        ctx.strokeStyle = 'grey';
        
        ctx.font='bold 20px Arial';
        
        
        
        
        //ctx.drawImage(image, 10,10,100, 100, dataCenterBoxPosX+150, dataCenterBoxPosY, renderSize.width , renderSize.height);
        ctx.fillStyle = "#C0E6F6";
        ctx.fillRect(dataCenterBoxPosX, dataCenterBoxPosY, rectWidth, 60);
        ctx.fillStyle = 'black';
        ctx.fillText(datacenter.toUpperCase(),dataCenterBoxPosX+200,dataCenterBoxPosY+40);
        ctx.rect(dataCenterBoxPosX, dataCenterBoxPosY, rectWidth, 60);
        ctx.rect(dataCenterBoxPosX, dataCenterBoxPosY, rectWidth, rectHeight+50);
        //ctx.clip();
        
        ctx.setLineDash([0,0]);
        ctx.stroke();
        ctx.strokeStyle = '#B0F79E';
        
        
        
        
        
        var coordinatesArr = new Array();
        coordinatesArr.push(dataCenterBoxPosX+130);
        coordinatesArr.push(dataCenterBoxPosY+25);
        
        dataCenterPosMap.set(datacenter, coordinatesArr);
        
        //var pos = 80;
        
        var appPosX = dataCenterBoxPosX;
        var appPosY = dataCenterBoxPosY+80;
        
        Array.from(map.keys()).map(app => {
            var day = map.get(app);
            var ballSize = 0
            if(day > 20){
                ballSize = 20;
            } else {
                ballSize = day;
            }
            
            
            //var ballX = Math.floor(Math.random()*10);
            var ballX = (appPosX + ballSize);
            
            var ballY = (appPosY);
            
            ctx.beginPath();
            
            ctx.arc(ballX+10,ballY+ ballSize+10,ballSize,0*Math.PI,2*Math.PI);
            
            ctx.fillStyle = '#B0F79E';
            
            
            
            ctx.fill();
            ctx.strokeStyle = 'grey';
            //ctx.strokeStyle = '#B0F79E';
            ctx.stroke();
            
            
            
            
            
            var appCoordinatesArr = new Array();
            appCoordinatesArr.push(ballX+10);
            appCoordinatesArr.push(ballY+ ballSize+10);
            appPosMap.set(app, appCoordinatesArr);
            
            
            appPosX = appPosX + ballSize*2+10;
            appPosY = appPosY;
            if((appPosX >= pos-ballSize)){
                appPosY = appPosY +ballSize*2+20;
                appPosX = dataCenterBoxPosX;
            }
            
            
        });
        
        
        dataCenterBoxPosX = dataCenterBoxPosX + 500;
        if((dataCenterBoxPosX + 400 + 40) >= 1200){
            dataCenterBoxPosY = dataCenterBoxPosY + 500;
            dataCenterBoxPosX = 40;
        }
        pos = pos+ 520;
        
    });
    
    
    Array.from(appPosMap.keys()).map(app => {
    var appPosArr = appPosMap.get(app);
        ctx.fillStyle = 'black';
            ctx.font = "11px Helvetica ";
            ctx.textAlign = "center";
            ctx.fillText(app,appPosArr[0],appPosArr[1]+5);
            
            
    });
    
}
function flashyText(app, appPosArr) {
    var count = 10,
        timer = setInterval(function() {
            count--;
            if( count%2 == 1) {
                ctx.fillStyle = 'white';
                ctx.fillText(app,appPosArr[0],appPosArr[1]+5);
                //ctx.fill();
            }
            else {
                // don't draw it (ie. clear it off)
            }
            if( count == 0) clearInterval(timer);
        },500);
}





animate();
</script> 

</body>
</html>

My output: enter image description here Expected:

enter image description here

Help me to solve this using HTML canvas



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source