Warve
Warve

Reputation: 511

jQuery random positioning infinite loop issue

Trying to randomly position balloons within it's container without overlapping. Think I've got the positioning correct however an infinite loop is happening when I push the positions variable. I can't see where it's going wrong. The balloons are being dynamically added to the DOM via append() and have placed within a window load function, so it should work.

Code is:

jQuery(window).load(function() {
    // Balloon positioning
    var containerW = 800;
    var containerH = 500;
    var positions = [];
    $('.balloony').each(function() {
        var coords = {
            w: $(this).outerWidth(true),
            h: $(this).outerHeight(true)
        };
        var success = false;
        while (!success)
        {
            coords.x = parseInt(Math.random() * (containerW-coords.w));
            coords.y = parseInt(Math.random() * (containerH-coords.h));
            var success = true;
            $.each(positions, function(){
                if (
                    coords.x <= (this.x + this.w) &&
                    (coords.x + coords.w) >= this.x &&
                    coords.y <= (this.y + this.h) &&
                    (coords.y + coords.h) >= this.y
                )
                {
                    success = false;
                }
            });
        }
        // positions.push(coords);
        $(this).css({
            top: coords.y + 'px',
            left: coords.x + 'px'
        });
    });
});

Fiddle is: https://jsfiddle.net/g91rdq69/ (Enabling positions.push causes fiddle to crash)

Thanks!

Upvotes: 0

Views: 109

Answers (2)

Alex Kudryashev
Alex Kudryashev

Reputation: 9470

The problem is in here: Your balloony's don't fit the container

.balloony {
      background-color: red;
      width: 30px;/*110px;*/ /*here*/
      height: 70px;
      ...

I made minimal changes in JS as well.

jQuery(document).ready(function() {
        // Balloon positioning
        var containerW = 800;
        var containerH = 500;
        var positions = [];
        $('.balloony').each(function() {
            var coords = {
                w: $(this).outerWidth(true),
                h: $(this).outerHeight(true)
            };
            var success = false;
            while (!success)
            {
                coords.x = parseInt(Math.random() * (containerW-coords.w));
                coords.y = parseInt(Math.random() * (containerH-coords.h));
                var success = true;
                $.each(positions, function(){
                //console.log(this);
                    if (
                        coords.x <= (this.x + this.w) &&
                        (coords.x + coords.w) >= this.x &&
                        coords.y <= (this.y + this.h) &&
                        (coords.y + coords.h) >= this.y
                    )
                    {
                        success = false;
                        return false; //break .each if found
                    }
                });
            }
             positions.push(coords);
            $(this).css({
                top: coords.y + 'px',
                left: coords.x + 'px'
            });
        });
        });//added

Upvotes: 1

abhinsit
abhinsit

Reputation: 3272

You have redefined variable success inside loop and hence changed its scope. So success with outer scope that will break loop is not changing resulting in infinite loop.

Hence change var success = true; inside loop to success = true;

jQuery(window).load(function() {
    // Balloon positioning
    var containerW = 800;
    var containerH = 500;
    var positions = [];
    $('.balloony').each(function() {
        var coords = {
            w: $(this).outerWidth(true),
            h: $(this).outerHeight(true)
        };
        var success = false;
        while (!success)
        {
            coords.x = parseInt(Math.random() * (containerW-coords.w));
            coords.y = parseInt(Math.random() * (containerH-coords.h));
            success = true;
            $.each(positions, function(){
                if (
                    coords.x <= (this.x + this.w) &&
                    (coords.x + coords.w) >= this.x &&
                    coords.y <= (this.y + this.h) &&
                    (coords.y + coords.h) >= this.y
                )
                {
                    success = false;
                }
            });
        }
        // positions.push(coords);
        $(this).css({
            top: coords.y + 'px',
            left: coords.x + 'px'
        });
    });
});

Upvotes: 1

Related Questions