3

All divs are being placed "randomly" like I need them to be, but they occasionally overlap. It's just a matter of chance. How can I prevent that from happening? (Ideally I'd be able to set a minimum distance between them)

Can I achieve this by further developing the current javascript? Do I need consider a completely different approach?

I honestly don't know how to tackle this issue. Any guidance would be highly appreciated. Thanks.

html

<div id="box1" class="boxes">
<div id="text1">&nbsp;&nbsp;Lorem Ipsum Dolor Sit Amet&nbsp;&nbsp;</div>
</div>

<div id="box2" class="boxes">
<div id="text2">&nbsp;&nbsp;Lorem Ipsum Dolor Sit Amet&nbsp;&nbsp;</div>
</div>

<div id="box3" class="boxes">
<div id="text3">&nbsp;&nbsp;Lorem Ipsum Dolor Sit Amet&nbsp;&nbsp;</div>
</div>

<div id="box4" class="boxes">
<div id="text4">&nbsp;&nbsp;Lorem Ipsum Dolor Sit Amet&nbsp;&nbsp;</div>
</div>

css

.boxes {
    position: absolute;
}

#text1 {
    color: white;
    font-family: "Times", Times New Roman, serif;
    font-size: 16px;
    font-weight: bold;
    line-height: 24px;
    background-color: black;
}

#text2 {
    color: white;
    font-family: "Times", Times New Roman, serif;
    font-size: 16px;
    font-weight: bold;
    line-height: 24px;
    background-color: blue;
}

#text3 {
    color: white;
    font-family: "Times", Times New Roman, serif;
    font-size: 16px;
    font-weight: bold;
    line-height: 24px;
    background-color: green;
}

#text4 {
    color: white;
    font-family: "Times", Times New Roman, serif;
    font-size: 16px;
    font-weight: bold;
    line-height: 24px;
    background-color: red;
}

javascript

function setRandomPos(elements,x,dx){
    elements.each(function(){
        fixLeft=(Math.floor(Math.random()*x)*10) + dx;
        fixTop = (Math.floor(Math.random()*40)*10) + 180;
        $(this).offset({
            left: fixLeft,
            top: fixTop
            });
        });
}

setRandomPos($(".boxes"),40,40);

Fiddle

LrnWdlr
  • 35
  • 1
  • 5
  • There's no magic way for you to prevent this from happening. You will have to change the setRandomPos element so that before placing each element randomly, it needs to check the position of all the other elements and check if the new random position overlaps with any of them. See here for a method which checks if two divs overlap: http://stackoverflow.com/questions/14012766/detecting-whether-two-divs-overlap – HaukurHaf Jan 01 '15 at 17:22
  • @HaukurHaf even if it works, it will still allow them to touch, right? I'd need them to not touch each other. – LrnWdlr Jan 01 '15 at 17:35
  • Then you only need to add a few pixels to the collision check to make one of the divs seem a little larger. – HaukurHaf Jan 01 '15 at 17:38
  • @HaukurHaf That's it then! The problem is that looking at the code, I don't think I'm able implement it myself. I'm new to js... would you be able to help me? – LrnWdlr Jan 01 '15 at 17:44

1 Answers1

5

Ammend your JavaScript to the following. This stores each box's dimensions and checks each new box against overlaps.

var boxDims = new Array();

function setRandomPos(elements,x,dx){
  elements.each(function(){
    var conflict = true;
    while (conflict) {
        fixLeft=(Math.floor(Math.random()*x)*10) + dx;
        fixTop = (Math.floor(Math.random()*40)*10) + 180;
        $(this).offset({
            left: fixLeft,
            top: fixTop
        });
        var box = {
            top: parseInt(window.getComputedStyle($(this)[0]).top),
            left: parseInt(window.getComputedStyle($(this)[0]).left),
            width: parseInt(window.getComputedStyle($(this)[0]).width),
            height: parseInt(window.getComputedStyle($(this)[0]).height)
        }
        conflict = false;
        for (var i=0;i<boxDims.length;i++) {
            if (overlap(box,boxDims[i])) {
                conflict = true;
                break;
            } else {
                conflict = false;
            }                   
        }
    }
    boxDims.push(box)
    
  });
}

function overlap(box1,box2) {
  var x1 = box1.left
  var y1 = box1.top;
  var h1 = box1.height;
  var w1 = box1.width;
  var b1 = y1 + h1;
  var r1 = x1 + w1;
  var x2 = box2.left;
  var y2 = box2.top;
  var h2 = box2.height;
  var w2 = box2.width;
  var b2 = y2 + h2;
  var r2 = x2 + w2;

  var buf = 24;

  if (b1 + buf < y2 || y1 > b2 + buf || r1 + buf < x2 || x1 > r2 + buf) return false;
  return true;
}

setRandomPos($(".boxes"),40,40);
mertyildiran
  • 6,477
  • 5
  • 32
  • 55
suncannon
  • 194
  • 1
  • 9
  • How do I make "the divs seem a little larger" (in HaukurHaf's words) to prevent them from getting too close to each other? – LrnWdlr Jan 01 '15 at 17:56
  • How far apart do you need them to be? You might want to edit your original post to be more specific then, because right now you only ask about preventing overlaps. – suncannon Jan 01 '15 at 18:02
  • A minimum of 24 pixels, the current height of the boxes. Is that hard to do? because that value might change in the future... yeah, sorry about that, I'm gonna edit the original post. thanks. – LrnWdlr Jan 01 '15 at 18:07
  • I added a variable buffer distance `buf` in the overlap function. It's set to 24 but you should be able to change it. Warning that if you make this buffer too large, the program may crash because divs will be unplaceable. – suncannon Jan 01 '15 at 18:23
  • @suncannon I've fixed the wrong `box1` and `box2` references inside `overlap()` function by editing your answer. – mertyildiran Oct 01 '20 at 23:51
  • Why get values from computed styles when you can do `el.getBoundingClientRect()` ? – nullspace Oct 23 '20 at 07:41