JavaScript to calculate random position for divs with no collision - javascript

I'm trying to draw a bunch of divs inside of a container in such a way that they are randomly positioned every time the page is loaded and that there is no overlapping. I seem to be stuck in an infinite loop and without the sources loading in Chrome before crashing the page, I can't debug properly.
Here's my code:
$(document).ready(function() {
var filledAreas = new Array();
var minX = 50;
var maxX = $("#banner").width() - 150;
var minY = 50;
var maxY = $("#banner").height() - 150;
var loops = 0;
var loopsMax = 100;
for (var i = 0; i < 15; i++) {
var color = '#' + Math.round(0xffffff * Math.random()).toString(16);
$newDiv = $("<div class='bubble-outer'></div>").css({
'width': '100px',
'height': '100px',
'background-color': color,
});
var randX = 0;
var randY = 0;
var area;
do {
randX = Math.floor(Math.random() * (maxX - minX + 1)) + minX;
randY = Math.floor(Math.random() * (maxY - minY + 1)) + minY;
var area = {
'left': randX,
'top': randY,
'right': randX + 100,
'bottom': randY + 100,
};
} while (loops < loopsMax && checkOverlap(area))
filledAreas.push(area)
$newDiv.css({
'position': 'absolute',
'left': randX + 'px',
'top': randY + 'px',
'display': 'none'
}).delay(1000).appendTo("#banner").fadeIn(300);
}
console.log("Loops: " + loops);
function checkOverlap(area) {
for (var i = 0; i < filledAreas.length; i++) {
var check = filledAreas[i];
if (area.right < check.left && area.bottom < check.top &&
check.right < area.left && check.bottom < area.top) {
loops++;
continue;
} else {
return true;
}
return false;
}
}
});

Since you used my algorithm, might as well post it as an answer!
As with many things, it is easier to cheat than to do exactly what you want to do.
Doing it the "proper" way would involve detecting collisions, which gets very tricky very fast.
However, here's a nice way to cheat at it:
Divide the area into a grid. Each grid square must be at least as big as your biggest element for this to work correctly.
For each element, pick a grid square. If that grid square hasn't been taken yet, place your element somewhere inside that grid square at random.
And... that's it! Now you are guaranteed to never have any collisions, and it looks pretty random because it is :)

Related

create random rectangles with random colors without overlapping using javascript

How can i create something like this in HTML using javascript?
Actually I know how to create rectangles in HTML but want to do something like this. HTML canvas can be of any size but whenever page is loaded multiple squares are generated with random sizes and colors without overlapping. When I'm trying to do this rectangles are generated in a list form. I'm a web developer(ruby on rails oriented) but new to such javascript stuff. Any help will be appreciated.
html:
<body>
<div id="randBlock" >
</div>
</body>
javascript:
(function makeDiv(){
var divsize = ((Math.random()*100) + 50).toFixed();
var color = '#'+ Math.round(0xffffff * Math.random()).toString(16);
$newdiv = $('#randBlock').css({
'width':divsize+'px',
'height':divsize+'px',
'background-color': color
});
var posx = (Math.random() * ($(document).width() - divsize)).toFixed();
var posy = (Math.random() * ($(document).height() - divsize)).toFixed();
$newdiv.css({
'position':'absolute',
'left':posx+'px',
'top':posy+'px',
'display':'none'
}).appendTo( 'body' ).fadeIn(100).delay(300).fadeOut(200, function(){
$(this).remove();
makeDiv();
});
})();
A solution with canvas (so I understand the question).
With built-in collision detecting isInside().
Edit: Better random support, does not run forever, a hint from Drawing a 1px thick line in canvas creates a 2px thick line and a little bit from this answer Random Color generator in Javascript
function getRandomColor() {
var color = '#';
for (var i = 0; i < 6; i++) {
color += (Math.random() * 16 | 0).toString(16);
}
return color;
}
function Point(x, y) {
this.x = x;
this.y = y;
}
function Rectangle(p1, p2) {
this.p1 = p1;
this.p2 = p2;
}
Rectangle.prototype.isInside = function (r) {
function check(a, b) {
return (
a.p1.x <= b.p1.x && b.p1.x <= a.p2.x && a.p1.y <= b.p1.y && b.p1.y <= a.p2.y ||
a.p1.x <= b.p2.x && b.p2.x <= a.p2.x && a.p1.y <= b.p2.y && b.p2.y <= a.p2.y ||
a.p1.x <= b.p2.x && b.p2.x <= a.p2.x && a.p1.y <= b.p1.y && b.p1.y <= a.p2.y ||
a.p1.x <= b.p1.x && b.p1.x <= a.p2.x && a.p1.y <= b.p2.y && b.p2.y <= a.p2.y
);
}
return check(this, r) || check(r, this);
}
function generateRectangles() {
function p() { return Math.random() * 300 | 0; }
function s() { return 50 + Math.random() * 150 | 0; }
var rectangles = [],
r, size, x, y, isInside, i, counter = 0;
for (i = 0; i < 20; i++) {
counter = 0;
do {
counter++;
x = p();
y = p();
size = s();
r = new Rectangle(new Point(x, y), new Point(x + size, y + size));
isInside = rectangles.some(function (a) {
return a.isInside(r);
});
} while (isInside && counter < 1000);
counter < 1000 && rectangles.push(r);
}
return rectangles;
}
function drawRectangles(rectangles) {
var canvas = document.getElementById("canvas"),
ctx = canvas.getContext("2d");
rectangles.forEach(function (a) {
ctx.lineWidth = 1;
ctx.strokeRect(a.p1.x + 0.5, a.p1.y + 0.5, a.p2.x - a.p1.x - 1, a.p2.y - a.p1.y - 1);
ctx.fillStyle = getRandomColor();
ctx.fillRect(a.p1.x + 0.5, a.p1.y + 0.5, a.p2.x - a.p1.x - 1, a.p2.y - a.p1.y - 1);
});
}
var rectangles = generateRectangles();
drawRectangles(rectangles);
<canvas id="canvas" width="500" height="500"></canvas>
You already have it drawing one random square with random position. It's easy to go from there to drawing many - simply have a loop for adding more than one div. Of course, then you need to give each one a random id, but that's easy enough. The problem is that this will allow overlapping.
Simplest case: allowing overlap
function makeDiv(i) {
var divsize = ((Math.random() * 100) + 50).toFixed();
var color = '#' + Math.round(0xffffff * Math.random()).toString(16);
var posx = (Math.random() * ($(document).width() - divsize)).toFixed();
var posy = (Math.random() * ($(document).height() - divsize)).toFixed();
var divid = 'randBlock' + i;
$('#randBlock').append("<div id='" + divid + "'>");
$('#' + divid).css({
'width': divsize + 'px',
'height': divsize + 'px',
'background-color': color,
'position': 'absolute',
'left': posx + 'px',
'top': posy + 'px'
});
}
for (var i = 0; i < 10; ++i) {
makeDiv(i);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<body>
<div id="randBlock">
</div>
</body>
If you want to guarantee it doesn't overlap, you have a lot more work to do, unless there's some CSS magic you can do, which is very possible, but I'm not aware of it. You would have to track the position and size of each square, and only fit the results into areas that are clear.
Depending on your exact requirements, your algorithm will be different. You're going to have to have some constraint - either in the maximum size of the squares, the requirement on overlapping, a maximum number of squares that you want to fit, or allow the squares to become increasingly small. I'll give you a verbal walkthrough for two of these. There's a working snippet for the grid idea. From what you added in the comments, that may be sufficient.
You've already built in a fixed size, so maybe the best idea is to use that size as a basis, and create a grid. In that case, you'll know you can have one square in each gridsquare. Have an array that stores each gridsquare position, and randomly choose from (1 to the length of that array) - 1. In that gridsquare, fit a square, very similarly to the function you currently have. Its size is the max you already have set, and its position within that box can be random based on the size.
Gridded case
var fixedScale = 100;
var fixedConstant = 50;
var fixedMax = fixedScale + fixedConstant;
var gridCols = (($(document).width() / fixedMax) + 1).toFixed();
var gridRows = (($(document).height() / fixedMax) + 1).toFixed();
var grid = [];
for (var row = 0; row < gridRows; ++row) {
for (var col = 0; col < gridCols; ++col) {
var index = row * gridCols + col;
grid[index] = {row: row, col: col};
}
}
function makeDiv(i) {
var gridId = Math.floor(Math.random() * grid.length);
var divsize = ((Math.random() * fixedScale) + fixedConstant).toFixed();
console.log(gridId + ", grid.length = " + grid.length);
var color = '#' + Math.round(0xffffff * Math.random()).toString(16);
var posx = grid[gridId].col * fixedMax;
var posy = grid[gridId].row * fixedMax;
var offsetx = (Math.random() * (fixedMax - divsize)).toFixed();
var offsety = (Math.random() * (fixedMax - divsize)).toFixed();
posx = +posx + +offsetx;
posy = +posy + +offsety;
var divid = 'randBlock' + i;
grid.splice(gridId, 1);
$('#randBlock').append("<div id='" + divid + "'>");
$('#' + divid).css({
'width': divsize + 'px',
'height': divsize + 'px',
'background-color': color,
'position': 'absolute',
'left': posx + 'px',
'top': posy + 'px'
});
}
for (var i = 0; i < 10; ++i) {
makeDiv(i);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<body>
<div id="randBlock">
</div>
</body>
You can have infinite (but diminishing squares) using the following fact: any time you add a square into an empty area, it will leave four rectangles of remaining space in that area. Any time you make a colored square, you could actually make 5 divs: the colored square, the empty area on its top, its right, its bottom and its left. Attribute the empty ones with a specific class. Then, look through all divs that have that "empty" class, and set your max size to the max of the empty divs. When you create your next colored square, pick a random div that is at least as big as the square.
Obviously, the code for these is not entirely trivial. The choice you make in your requirements and constraints will have a huge impact on your coding effort.

JavaScript Css Animation

I have a Javascript animation at http://dev17.edreamz3.com/css/
All code works, however, there are performance problems. on Desktop, its good, On mobile things are so slow that it's unusable. I want to optimize the animation so that it runs smoothly on mobile. It can take 20 seconds or more for the animation to render.
Right now the way the code is designed is in js/anim.js there is a render() function that gets executed every time a scroll event happens. The problem is that this routine is not efficient, that's what I think of. Each time render() executes it loops through all the paths and sections of the maze and redraws them, is there any alternative way or a strategy to get it working both on mobile as well as desktop.
var offPathTime = 1000;
window.offSection = -1;
function render() {
// var top = ($window.scrollTop() + (0.4 * $window.height())) / window.scale;
var top = ($('.parent-div').scrollTop() + (0.4 * $('.parent-div').height())) / window.scale;
top -= 660;
top /= mazeSize.h;
if (window.offSection != -1) {
$body.addClass("blockScroll");
$('.parent-div').addClass("blockScroll");
// var wtop = $window.scrollTop() / window.scale;
var wtop = $('.parent-div').scrollTop() / window.scale;
wtop -= 660;
wtop /= mazeSize.h;
var $offSection = $("#offSection" + window.offSection);
var $section = $("#section" + window.offSection);
$(".section").removeClass("sectionActive");
$offSection.addClass("sectionActive");
$section.addClass("sectionActive");
var sTop = 200 -(mazeSize.h * (window.offSections[window.offSection].cy - wtop));
$container.animate({
left: 290 -(mazeSize.w * window.offSections[window.offSection].cx) + "px",
top: sTop + "px"
}, offPathTime);
// Path
var lr = offPaths[window.offSection].x1 > offPaths[window.offSection].x0;
var dx = Math.abs(offPaths[window.offSection].x1 - offPaths[window.offSection].x0);
var dashw = (dx * mazeSize.w) | 0;
$offPaths[window.offSection].css("width", "0px");
$offPaths[window.offSection].show();
if (lr) {
$offPaths[window.offSection].animate({
width: dashw + "px"
}, offPathTime);
} else {
var x0 = offPaths[window.offSection].x0 * mazeSize.w;
var x1 = offPaths[window.offSection].x1 * mazeSize.w;
$offPaths[window.offSection].css("left", x0 + "px");
$offPaths[window.offSection].animate({
width: dashw + "px",
left: x1 + "px"
}, offPathTime);
}
return;
}
$body.removeClass("blockScroll");
$('.parent-div').removeClass("blockScroll");
$(".offPath").hide();
if ($container.css("top") != "0px") {
$container.animate({
left: "-1550px",
top: "0px"
}, 500);
}
var pathIdx = -1;
var path0 = paths[0];
var path1;
var inPath = 0;
var i;
var curTop = 0;
var found = false;
for (i=0; i<paths.length; i++) {
var top0 = (i == 0) ? 0 : paths[i-1].y;
var top1 = paths[i].y;
if (top >= top0 && top < top1) {
pathIdx = i;
path1 = paths[i];
inPath = (top - top0) / (top1 - top0);
found = true;
if (i > 0) {
var dy = paths[i].y - paths[i-1].y;
var dx = paths[i].x - paths[i-1].x;
var vert = dx == 0;
if (vert)
$paths[i-1].css("height", (dy * mazeSize.h * inPath) + "px");
$paths[i-1].show();
}
} else if (top >= top0) {
path0 = paths[i];
var dy = paths[i].y - top0;
var vert = dy != 0;
if (i > 0) {
if (vert)
$paths[i-1].css("height", (dy * mazeSize.h) + "px");
$paths[i-1].show();
}
} else {
if (i > 0) {
$paths[i-1].hide();
}
}
curTop = top1;
}
// Check for an active section
$(".section").removeClass("sectionActive");
var section;
for (i=0; i<sections.length; i++) {
var d = Math.abs(sections[i].cy - (top - 0.05));
if (d < 0.07) {
var $section = $("#section" + i);
$section.addClass("sectionActive");
}
}
}
1) At the very least - assign all DOM objects to variables outside of the function scope. Like this:
var $parentDiv = $('.parent-div');
var $sections = $(".section");
...
function render() {
...
2) Also you should probably stop animation before executing it again, like this:
$container.stop(true).animate({
...
If you are running render() function on scroll - it will run many times per second. stop() helps to prevent it somewhat.
3) If it will not be sufficient - you can switch from jQuery to Zepto(jQuery-like api, but much faster and uses css transitions for animations) or to Velocity(basically drop-in replacement for jQuery $.animate and much faster than original) or even to GSAP - much more work obviously, but it is very fast and featured animation library.

DIVs to randomly fadeIn on page

Okay, I've seen a few things that sort of * answer my question, but none of them quite do what I want to do / I'd like to understand how to do this myself from start to finish as a learning exercise. I'm a novice at all this, so bear with me!
What I'm Trying to Do:
I have a black page and I'd like 20-30 small, white div boxes to fadeIn at random positions on the page (like stars is sort of the vibe I'm going for).
Ideally, they wouldn't overlap and they would be randomly sized between 5px and 10px, but I recognize that this might be getting a little too complicated.
Here's what I have so far
I've been working off this jsfiddle and well as this one. This is what I've come up with (that doesn't work, they all fade in equally spaced in a line and don't stay confined from to the site)
Here's my jsfiddle, code below
function randomPosition() {
var h = $(window).height()-10;
var w = $(window).width()-10;
var newHeight = Math.floor(Math.random() * h);
var newWidth = Math.floor(Math.random() * w);
return [newHeight, newWidth];
}
$(document).ready(function() {
var newPosition = randomPosition();
$('.star').css( {
'margin-left':newPosition[1]+'px',
'margin-top':newPosition[0]+'px'
}).each(function(index) { $(this).delay(1500*index).fadeIn('slow');
})
});
CSS
body {
background-color: black;
}
.star {
height: 10px;
width: 10px;
background-color: white;
display: none;
}
HTML (is there a way to do this with just a for loop or something similar?)
<div class="star"> </div>
<div class="star"> </div>
<div class="star"> </div>
<div class="star"></div>
The sizing and positioning isn't too hard. The thing is to do it all in the each loop - currently you get 1 position and use it for everything. Also you will want to make them position:absolute so they don't go off the page.
I've updated your fiddle to set the random position and a size between 5 and 10px:
The overlapping is a bit harder. You need to keep track of the sizes and positions you have generated and in the same .each function compare the current generated size+position to the previous ones to check for overlapping.
http://jsfiddle.net/5ocb5aww/3/
function randomPosition() {
var h = $(window).height()-10;
var w = $(window).width()-10;
var newHeight = Math.floor(Math.random() * h);
var newWidth = Math.floor(Math.random() * w);
return [newHeight, newWidth];
}
function randomSize() {
return Math.round(Math.random() * 5) + 5;
}
$(document).ready(function() {
// stores generated star positions
var stars = [];
$('.star').each(function(index) {
var newPosition, newSize;
// check for overlap
var isOverlap = true;
while(isOverlap)
{
newPosition = randomPosition();
newSize = randomSize();
// check previous stars to see if an edge of this one overlaps
isOverlap = $.grep(stars, function(s) {
return (
(newPosition[1] >= s.x1 && newPosition[1] <= s.x2)
|| (newPosition[1]+newSize >= s.x1 && newPosition[1]+newSize <= s.x2)
)
&& (
(newPosition[0] >= s.y1 && newPosition[0] <= s.y2)
|| (newPosition[0]+newSize >= s.y1 && newPosition[0]+newSize <= s.y2)
);
}).length > 0;
}
// store to check later stars against it
stars.push({
x1: newPosition[1],
x2: newPosition[1] + newSize,
y1: newPosition[0],
y2: newPosition[0] + newSize,
size: newSize});
$(this).css({
'margin-left':newPosition[1]+'px',
'margin-top':newPosition[0]+'px',
'width':newSize + 'px',
'height':newSize + 'px'
});
$(this).delay(800*index).fadeIn('slow');
})
});
Here is my approach to your exercise ... the overlapping position would require a little bit more effort ... I'll leave you that to sort for yourself (may require restructuring the code I'm handing here)
jsFiddle Demo
JS
function starDust(wdt, hgt, tSt, tAp){
var timer = tAp * 1000;
var defInt = tSt,
starInt = setInterval(function(){
var posX = Math.floor((Math.random() * wdt) + 1),
posY = Math.floor((Math.random() * hgt) + 1),
size = Math.floor((Math.random() * 10) + 1);
$('body').append('<div class="star"></div>');
$('.star:last').css({'width':size,'height':size,'left':posX,'top':posY}).hide().fadeIn('slow');
var totalStars = $('.star').length;
if(totalStars == defInt){
clearInterval(starInt);
}
}, timer);
}
$(function(){
// Function arguments: starDust(max X position in px, max Y position in px, total number of stars, time in seconds between stars show);
starDust(600,300,25,1);
});
CSS
body{
background-color:#000;
}
.star{
position: absolute;
background-color:#fff;
min-width:5px;
min-height:5px;
}

Algorithm for placing dashboard panels in unoccupied space

I'm working on a portal/dashboard type interface which has panels/widgets that can be freely dragged around the dashboard space as long as they don't overlay any other panels. New panels can be added to the dashboard via a menu containing all available panels, and when a menu item is clicked, the panel is placed into the dashboard. The panels currently occupying the dashboard space are all represented in an object like this:
{
'panel_1': { top: 0, left: 0, width: 300, height: 350 },
'panel_2': { top: 0, left: 370, width: 200, height: 275 },
'panel_3': { top: 370, left: 0, width: 275, height: 400 },
...
}
My question is, what is a valid algorithm that would, when the user clicks one in the menu, correctly place a new panel (of a given width and height) in unoccupied space that is closest to a left and top (x and y) value of 0, 0, without overlapping any of the existing panels?
I think, simple bruteforce algorithm will fit you. As I remember, fit rectangle solve another problem
Iterate over your dashboard axis to find out, whether you can place your rectangle, until X < rectangle.widh + dashboard.width, same for Y.
Foreach X,Y on dashboard iterate over every panel to find whether they overlap. You can apply some optimization, to decrease amount of iteration. If panel overlap rectangle, you can increase X or Y(which is in nested loop) not by 1, but by width or height of panel.
In most cases, you will not make dashboard.width*dashboard.height*panel.count iteration. With some optimization, it will find best fit rather quick
I know this is an old question but if anyone wants a proof of concept then it looks like this:
function findSpace(width, height) {
var $ul = $('.snap-layout>ul');
var widthOfContainer = $ul.width();
var heightOfContainer = $ul.height();
var $lis = $ul.children('.setup-widget'); // The li is on the page and we dont want it to collide with itself
for (var y = 0; y < heightOfContainer - height + 1; y++) {
var heightOfShortestInRow = 1;
for (var x = 0; x < widthOfContainer - width + 1; x++) {
//console.log(x + '/' + y);
var pos = { 'left': x, 'top': y };
var $collider = $(isOverlapping($lis, pos, width, height));
if ($collider.length == 0) {
// Found a space
return pos;
}
var colliderPos = $collider.position();
// We have collided with something, there is no point testing the points within this widget so lets skip them
var newX = colliderPos.left + $collider.width() - 1; // -1 to account for the ++ in the for loop
x = newX > x ? newX : x; // Make sure that we are not some how going backwards and looping forever
var colliderBottom = colliderPos.top + $collider.height();
if (heightOfShortestInRow == 1 || colliderBottom - y < heightOfShortestInRow) {
heightOfShortestInRow = colliderBottom - y; // This isn't actually the height its just the distance from y to the bottom of the widget, y is normally at the top of the widget tho
}
}
y += heightOfShortestInRow - 1;
}
//TODO: Add the widget to the bottom
}
function isOverlapping($obsticles, tAxis, width, height) {
var t_x, t_y;
if (typeof (width) == 'undefined') {
// Existing element passed in
var $target = $(tAxis);
tAxis = $target.position();
t_x = [tAxis.left, tAxis.left + $target.outerWidth()];
t_y = [tAxis.top, tAxis.top + $target.outerHeight()];
} else {
// Coordinates and dimensions passed in
t_x = [tAxis.left, tAxis.left + width];
t_y = [tAxis.top, tAxis.top + height];
}
var overlap = false;
$obsticles.each(function () {
var $this = $(this);
var thisPos = $this.position();
var i_x = [thisPos.left, thisPos.left + $this.outerWidth()]
var i_y = [thisPos.top, thisPos.top + $this.outerHeight()];
if (t_x[0] < i_x[1] && t_x[1] > i_x[0] &&
t_y[0] < i_y[1] && t_y[1] > i_y[0]) {
overlap = this;
return false;
}
});
return overlap;
}

random position of divs in javascript

I'm trying to make Divs to appear randomly anywhere on a webpage with javascript. So a div appears then disappears, then another div appears somewhere else on the page then disappears, then another div appears again in another random spot on the page then disappears, and so on.
I'm not sure on how to generate random units in pixels or what technique to use to generate random positions.
How do I do that? Here's my code:
var currentDivPosition = myDiv.offset(),
myDivWidth = myDiv.width(),
myDivHeight = myDiv.height(),
var myDiv = $('<div>'),
finalDivPositionTop, finalDivPositionLeft;
myDiv.attr({ id: 'myDivId', class: 'myDivClass' }); // already defined with position: absolute is CSS file.
// Set new position
finalDivPositionTop = currentDivPosition.top + Math.floor( Math.random() * 100 );
finalDivPositionLeft = currentDivPosition.left + Math.floor( Math.random() * 100 );
myDiv.css({ // Set div position
top: finalDivPositionTop,
left: finalDivPositionLeft
});
$('body').append(myDiv);
myDiv.text('My position is: ' + finalDivPositionTop + ', ' + finalDivPositionLeft);
myDiv.fadeIn(500);
setTimeout(function(){
myDiv.fadeOut(500);
myDiv.remove();
}, 3000);
Here's one way to do it. I'm randomly varying the size of the div within a fixed range, then setting the position so the object is always placed within the current window boundaries.
(function makeDiv(){
// vary size for fun
var divsize = ((Math.random()*100) + 50).toFixed();
var color = '#'+ Math.round(0xffffff * Math.random()).toString(16);
$newdiv = $('<div/>').css({
'width':divsize+'px',
'height':divsize+'px',
'background-color': color
});
// make position sensitive to size and document's width
var posx = (Math.random() * ($(document).width() - divsize)).toFixed();
var posy = (Math.random() * ($(document).height() - divsize)).toFixed();
$newdiv.css({
'position':'absolute',
'left':posx+'px',
'top':posy+'px',
'display':'none'
}).appendTo( 'body' ).fadeIn(100).delay(1000).fadeOut(500, function(){
$(this).remove();
makeDiv();
});
})();
Edit: For fun, added a random color.
Edit: Added .remove() so we don't pollute the page with old divs.
Example: http://jsfiddle.net/redler/QcUPk/8/
Let's say you have this HTML:
<div id="test">test div</div>
And this CSS:
#test {
position:absolute;
width:100px;
height:70px;
background-color:#d2fcd9;
}
Using jQuery, if you use this script, whenever you click the div, it will position itself randomly in the document:
$('#test').click(function() {
var docHeight = $(document).height(),
docWidth = $(document).width(),
$div = $('#test'),
divWidth = $div.width(),
divHeight = $div.height(),
heightMax = docHeight - divHeight,
widthMax = docWidth - divWidth;
$div.css({
left: Math.floor( Math.random() * widthMax ),
top: Math.floor( Math.random() * heightMax )
});
});
The way this works is...first you calculate the document width and height, then you calculate the div width and height, and then you subtract the div width from the document width and the div height from the document height and consider that the pixel range you're willing to put the div in (so it doesn't overflow out of the document). If you have padding and border on the div, you'll need to account for those values too. Once you've figured out the range, you can easily multiple that by Math.random() and find the random position of your div.
So once more: first find the dimensions of the container, then find the dimensions of your element, then subtract element dimensions from container dimensions, and THEN use Math.random() on that value.
The basic idea is encapsulated here:
http://jsfiddle.net/5mvKE/
Some bugs:
You missed to position the div absolutely. Otherwise it will not
work.
I think you need to ad 'px' to the numbers.
The map is made of strings
Right in your jQuery css setup:
myDiv.css({
'position' : 'absolute',
'top' : finalDivPositionTop + 'px',
'left' : finalDivPositionLeft + 'px'
});
I changed an existant code by this one for our website, you can see it on tweefox.nc
<script>
function draw() {
$(canvas).attr('width', WIDTH).attr('height',HEIGHT);
con.clearRect(0,0,WIDTH,HEIGHT);
for(var i = 0; i < pxs.length; i++) {
pxs[i].fade();
pxs[i].move();
pxs[i].draw();
}
}
function Circle() {
this.s = {ttl:8000, xmax:10, ymax:4, rmax:10, rt:1, xdef:950, ydef:425, xdrift:4, ydrift: 4, random:true, blink:true};
this.reset = function() {
this.x = (this.s.random ? WIDTH*Math.random() : this.s.xdef);
this.y = (this.s.random ? HEIGHT*Math.random() : this.s.ydef);
this.r = ((this.s.rmax-1)*Math.random()) + 1;
this.dx = (Math.random()*this.s.xmax) * (Math.random() < .5 ? -1 : 1);
this.dy = (Math.random()*this.s.ymax) * (Math.random() < .5 ? -1 : 1);
this.hl = (this.s.ttl/rint)*(this.r/this.s.rmax);
this.rt = Math.random()*this.hl;
this.s.rt = Math.random()+1;
this.stop = Math.random()*.2+.4;
this.s.xdrift *= Math.random() * (Math.random() < .5 ? -1 : 1);
this.s.ydrift *= Math.random() * (Math.random() < .5 ? -1 : 1);
}
this.fade = function() {
this.rt += this.s.rt;
}
this.draw = function() {
if(this.s.blink && (this.rt <= 0 || this.rt >= this.hl)) {
this.s.rt = this.s.rt*-1;
this.dx = (Math.random()*this.s.xmax) * (Math.random() < .5 ? -1 : 1);
this.dy = (Math.random()*this.s.ymax) * (Math.random() < .5 ? -1 : 1);
} else if(this.rt >= this.hl) this.reset();
var newo = 1-(this.rt/this.hl);
con.beginPath();
con.arc(this.x,this.y,this.r,0,Math.PI*2,true);
con.closePath();
var cr = this.r*newo;
g = con.createRadialGradient(this.x,this.y,0,this.x,this.y,(cr <= 0 ? 1 : cr));
g.addColorStop(0.0, 'rgba(255,255,255,'+newo+')');
g.addColorStop(this.stop, 'rgba(255,255,255,'+(newo*.2)+')');
g.addColorStop(1.0, 'rgba(255,255,255,0)');
con.fillStyle = g;
con.fill();
}
this.move = function() {
this.x += (this.rt/this.hl)*this.dx;
this.y += (this.rt/this.hl)*this.dy;
if(this.x > WIDTH || this.x < 0) this.dx *= -1;
if(this.y > HEIGHT || this.y < 0) this.dy *= -1;
}
this.getX = function() { return this.x; }
this.getY = function() { return this.y; }
}
$(document).ready(function(){
// if( /Android|AppleWebKit|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ) {
// } else {
if(document.getElementById('pixie')) {
WIDTH = $(window).width();
HEIGHT = $(window).height();
canvas = document.getElementById('pixie');
$(canvas).attr('width', WIDTH).attr('height',HEIGHT);
con = canvas.getContext('2d');
pxs = new Array();
rint = 60;
for(var i = 0; i < 50; i++) {
pxs[i] = new Circle();
pxs[i].reset();
}
setInterval(draw,rint);
}
// }
});
</script>

Categories