2

I want to put like 30 of <img class="anger"> elements with random size and random position inside the <div> container, but none of the .anger hitting one another.

Is it possible?

This is my code so far:

function loadAngers() {
    var wrp = '#angerContainer'; //the container
    var rectAvatar = $('#picAvatar')[0].getBoundingClientRect(); //rect of user avatar
    var rectWrapper = $(wrp)[0].getBoundingClientRect(); //rect of container
    listCoorditaes = [[
        rectAvatar.width,
        (rectAvatar.left+rectAvatar.right)/2,
        (rectAvatar.top+rectAvatar.bottom)/2
    ]];
    $(wrp).find('.anger').remove();
    for (var i=0; i<listAnger.length; i++) {
        var verb = listAnger[i].replace('assets/img/verb/','').replace('.png','').replace('-',' ');
        var anger = $('<img src="'+listAnger[i]+'" class="anger hvr-'+getRandom(listAnim)+'" data-verb="'+verb+'" style="position:absolute">');
        var paddingX = 100;
        var paddingY = 200;
        var wideX = rectWrapper.width - paddingX;
        var wideY = rectWrapper.height - paddingY - rectAvatar.top;
        var width = Math.round(30 + Math.random() * 70);
        var left;
        var top;
        var x;
        var y;
        var tubrukan;
        var coba = 0;
        do { //find the best coordinate
            tubrukan = false;
            coba++;
            x = Math.round(Math.random() * wideX) + paddingX/2;
            y = Math.round(Math.random() * wideY) + paddingY/2 + rectAvatar.top;
            left = x - width/2;
            top = y - width/2;
            for (var j=0; j<=i; j++) {
                var cekW = listCoorditaes[j][0];
                var cekX = listCoorditaes[j][1];
                var cekY = listCoorditaes[j][2];
                var difX = Math.abs( x - cekX );
                var difY = Math.abs( y - cekY );
                if (difX < cekW && difY < cekW) {
                    tubrukan = true;
                    break;
                }
            }
        }
        while(tubrukan && coba<3); //as I give up for eternal loop, I limit the loop with 3 tries.
        listCoorditaes.push([width,x,y]);

        anger.css('width',width+'px');
        anger.css('left',left);
        anger.css('top',top);
        anger.appendTo(wrp);
    }
}

This is the current result:

Screenshot

As we can see, the elements still overlap the other because I limit the loop. If I remove the limit, browser will endure endless loop and become not responding.

Do you have another better way to achieve it?

UPDATE:

My bad, I set the container height only 800px, that's why it can't contain all those <img> without overlapping, thus eternal loop happen. I made it to 2000px to see if it works. But the problem is still takes uncertain number of loops to find the best coordinate, so I still put limit to the loop thus overlap still happen several times.

enter image description here

Taufik Nur Rahmanda
  • 1,862
  • 2
  • 20
  • 36
  • Maybe you can split the screen to 30 parts and random only the part. You can also random the position inside the part to get more fillings of contingency. – Mosh Feu Apr 26 '18 at 12:09
  • @MoshFeu Thank you for the idea, but that would be like a grid which we can literally draw the table line between all of the image, not really at random position like I want. – Taufik Nur Rahmanda Apr 26 '18 at 12:45
  • Maybe you can append those images with random `margin` (random for each top, bottom, left, right) between, let's say, 0 to 100, so he result will be the same but you don't need to find a place. – Mosh Feu Apr 26 '18 at 13:38
  • @MoshFeu Ah, I get your idea. That's a good one to try. – Taufik Nur Rahmanda Apr 27 '18 at 00:08
  • Glad to hear :) If you have any questions about this (or any other topics) let me know. – Mosh Feu Apr 29 '18 at 08:28

0 Answers0