0

Fiddle

This is what I currently have. It's working, but I'd like to edit the random function so that the divs (this is just a mockup, there will be many, many more!) would be "evenly distributed" according to the browser's width, if that makes any sense. In a way that no horizontal scroll bar would ever be necessary!

I think this is a good example. Click the Designer's name (top left corner) and you'll see what I mean. Notice how those folders always use the whole window no matter how small or big it is? I want to mimic that behavior... I just don't know to go about it... edit the current script? a totally different approach?

Any input 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

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 = box2.top;
  var h1 = box1.height;
  var w1 = box1.width;
  var b1 = y1 + h1;
  var r1 = x1 + w1;
  var x2 = box1.left;
  var y2 = box1.top;
  var h2 = box1.height;
  var w2 = box1.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);
LrnWdlr
  • 35
  • 1
  • 5
  • 1
    That site is using [media queries](http://css-tricks.com/css-media-queries/) to obtain that effect. Perhaps you could read up on those? The bootstrap library provides a lot of that functionality out of the box. I don't understand what randomization has to do with your question. – JLRishe Jan 02 '15 at 13:29
  • Is there any specific reason you want to do this with Javascript when you can do this with CSS media queries. And indeed what @JLRishe says: there are a lot of frameworks that will handle the work for you. I like to use [PureCSS](http://www.purecss.io) – Michelangelo Jan 02 '15 at 13:36
  • They don't always use the whole window. If you keep clicking on Random, sometimes you'll see pretty large gaps. That's the nature of randomness. – Barmar Jan 02 '15 at 13:48
  • @JLRishe I think it has to do with randomization because right now the script has no correlation with the window's width... and they need to be linked, right? It needs to know that the items need to be placed across at least, let's say, 80% of the window's width. That's what i want to do... – LrnWdlr Jan 02 '15 at 14:14
  • @Mikey No reason, I just think the issue lies with the function that sets the randomization... – LrnWdlr Jan 02 '15 at 14:16
  • @Barmar When I say "the whole window" I'm referring to the width! If you were using a 4k monitor you'd notice the folders always spread out across, let's say, 80% of the window's width. Of course there will be gaps... but width wise they're always kind of evenly distributed. – LrnWdlr Jan 02 '15 at 14:17
  • So calculate a random fraction of the window's height and width. – Barmar Jan 02 '15 at 14:21
  • `setRandomPos($(".boxes"), window.width, 40)`. – Barmar Jan 02 '15 at 14:22
  • This is what I'm trying to prevent from happening. http://i.imgur.com/ZLQYZIu.png and never happens with that site! – LrnWdlr Jan 02 '15 at 14:27
  • @Barmar That simple? How so? – LrnWdlr Jan 02 '15 at 14:33
  • This is how she gets a value for position: `posX = Math.round(Math.random() * ($(window).width() - 100)) + 20; posY = Math.round(Math.random() * ($(window).height() - 200)) + 20;` – Michelangelo Jan 02 '15 at 14:34
  • Have you looked at the code on that site to see what he's doing? – Barmar Jan 02 '15 at 14:35
  • The code is in the function `folderRandom` in http://www.dominicrechsteiner.ch/fileadmin/templates/res/js/animations.js – Barmar Jan 02 '15 at 14:39
  • I've looked at it, I just don't really understand it... :( – LrnWdlr Jan 02 '15 at 14:40
  • @Barmar I know that. I just don't know how to replicate it in my mockup... – LrnWdlr Jan 02 '15 at 14:43

1 Answers1

1

I thought I'd share the tweaks and further solution I came up with. Making sure the parent container gets extended when there's not enough room inside the current window so no infinite loops will occur.

http://codepen.io/Shikkediel/pen/dPOVJp?editors=011

Made slightly less random by iterating over the screen's quadrants by a specified number first.

$(window).on('load', function() {

var spread, crest, boxes = [];

var margin = 40;
var itemwidth = 50;
var itemheight = 50;
var pad = 25;
var initial = 8;

setArea($(".boxes"));
placeRandom($(".boxes"));

function setArea(items) {

var range = 0, pitch = 0, total = 0;

items.each(function() {
range = $(this).width()+2*pad;
pitch = $(this).height()+2*pad;
total = total+range*pitch;
});

spread = $(window).width();
var term = $(window).height();
var edge = total/spread;

if (term < 4*edge) crest = 4*edge;
else crest = term;

$('#boxcontainer').css({'width': spread, 'height': crest});
spread = $(window).width();
$('#boxcontainer').width(spread);
}

function placeRandom(elements) {

var iter = 0;
var horizontal = spread/2;
var vertical = crest/2;

elements.each(function() {

var object = $(this), box;
iter++;
setPosition();

function setPosition() {

if (iter <= initial) {

var quadrant = iter%4;
if (quadrant == 0) quadrant = 4;
var spaceX = Math.round(Math.random()*(horizontal-itemwidth-margin));
var spaceY = Math.round(Math.random()*(vertical-itemheight-margin));
var bufferX, bufferY;

if (quadrant == 1) {
bufferX = margin;
bufferY = margin;
}
if (quadrant == 2) {
bufferX = horizontal;
bufferY = margin;
}
if (quadrant == 3) {
bufferX = horizontal;
bufferY = vertical;
}
if (quadrant == 4) {
bufferX = margin;
bufferY = vertical;
}
fixleft = spaceX+bufferX;
fixtop = spaceY+bufferY;
object.css({top: fixtop, left: fixleft});
}
else {
fixleft = Math.round(Math.random()*($(window).width()-itemwidth-2*margin))+margin;
fixtop = Math.round(Math.random()*($(window).height()-itemheight-2*margin))+margin;
object.css({top: fixtop, left: fixleft});
}

box = {
top: fixtop,
left: fixleft,
width: object.width(),
height: object.height()
}

if (iter == 1) boxes.push(box);
else {
for (var i=0; i < boxes.length; i++) {
if (encroachOn(box, boxes[i])) setPosition();
}
}
}
boxes.push(box);
object.show();
});
}

function encroachOn(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;

return (x1 < r2+pad && r1+pad > x2 && y1 < b2+pad && b1+pad > y2);
}
});

An additional function for resizing is to be added as well.

Edit - a nice solution for the latter found here on Stackoverflow :

https://stackoverflow.com/a/5490021/3168107

Community
  • 1
  • 1
Shikkediel
  • 5,195
  • 16
  • 45
  • 77